diff --git a/graphics/battle_interface/healthbox_doubles_opponent.png b/graphics/battle_interface/healthbox_doubles_opponent.png index 3a494a52a..eaf0ee136 100644 Binary files a/graphics/battle_interface/healthbox_doubles_opponent.png and b/graphics/battle_interface/healthbox_doubles_opponent.png differ diff --git a/graphics/battle_interface/healthbox_doubles_player.png b/graphics/battle_interface/healthbox_doubles_player.png index a7af1acc5..a1bf7ca1a 100644 Binary files a/graphics/battle_interface/healthbox_doubles_player.png and b/graphics/battle_interface/healthbox_doubles_player.png differ diff --git a/graphics/battle_interface/healthbox_singles_opponent.png b/graphics/battle_interface/healthbox_singles_opponent.png index be88c22f6..12b35cbc6 100644 Binary files a/graphics/battle_interface/healthbox_singles_opponent.png and b/graphics/battle_interface/healthbox_singles_opponent.png differ diff --git a/graphics/battle_interface/healthbox_singles_player.png b/graphics/battle_interface/healthbox_singles_player.png index a395b6543..fa2924d57 100644 Binary files a/graphics/battle_interface/healthbox_singles_player.png and b/graphics/battle_interface/healthbox_singles_player.png differ diff --git a/include/battle_interface.h b/include/battle_interface.h index 0ce99239c..54ab22804 100644 --- a/include/battle_interface.h +++ b/include/battle_interface.h @@ -33,28 +33,29 @@ enum HP_BAR_FULL, }; -#define TAG_HEALTHBOX_PLAYER1_TILE 55039 -#define TAG_HEALTHBOX_PLAYER2_TILE 55040 -#define TAG_HEALTHBOX_OPPONENT1_TILE 55041 -#define TAG_HEALTHBOX_OPPONENT2_TILE 55042 +#define TAG_HEALTHBOX_PLAYER1_TILE 0xD6FF +#define TAG_HEALTHBOX_PLAYER2_TILE 0xD700 +#define TAG_HEALTHBOX_OPPONENT1_TILE 0xD701 +#define TAG_HEALTHBOX_OPPONENT2_TILE 0xD702 -#define TAG_HEALTHBAR_PLAYER1_TILE 55044 -#define TAG_HEALTHBAR_OPPONENT1_TILE 55045 -#define TAG_HEALTHBAR_PLAYER2_TILE 55046 -#define TAG_HEALTHBAR_OPPONENT2_TILE 55047 +#define TAG_HEALTHBAR_PLAYER1_TILE 0xD704 +#define TAG_HEALTHBAR_OPPONENT1_TILE 0xD705 +#define TAG_HEALTHBAR_PLAYER2_TILE 0xD706 +#define TAG_HEALTHBAR_OPPONENT2_TILE 0xD707 -#define TAG_HEALTHBOX_PALS_1 55049 -#define TAG_HEALTHBOX_PALS_2 55050 -#define TAG_HEALTHBOX_SAFARI_TILE 55051 -#define TAG_STATUS_SUMMARY_BAR_TILE 55052 +#define TAG_HEALTHBOX_PALS_1 0xD709 +#define TAG_HEALTHBOX_PALS_2 0xD70A +#define TAG_HEALTHBOX_SAFARI_TILE 0xD70B +#define TAG_STATUS_SUMMARY_BAR_TILE 0xD70C -#define TAG_STATUS_SUMMARY_BAR_PAL 55056 -#define TAG_STATUS_SUMMARY_BALLS_PAL 55058 -#define TAG_STATUS_SUMMARY_BALLS_TILE 55060 +#define TAG_STATUS_SUMMARY_BAR_PAL 0xD710 +#define TAG_STATUS_SUMMARY_BALLS_PAL 0xD712 -#define TAG_HEALTHBOX_PAL TAG_HEALTHBOX_PLAYER1_TILE -#define TAG_HEALTHBAR_PAL TAG_HEALTHBAR_PLAYER1_TILE -#define TAG_SHADOW_PAL TAG_HEALTHBOX_PLAYER1_TILE +#define TAG_STATUS_SUMMARY_BALLS_TILE 0xD714 + +#define TAG_HEALTHBAR_PAL TAG_HEALTHBAR_PLAYER1_TILE +#define TAG_HEALTHBOX_PAL TAG_HEALTHBOX_PLAYER1_TILE +#define TAG_SHADOW_PAL TAG_HEALTHBOX_PLAYER1_TILE #define TAG_SHADOW_TILE 0xD759 @@ -107,39 +108,37 @@ enum HEALTHBOX_SAFARI_BALLS_TEXT }; -enum BattleCoordTypes GetBattlerCoordsIndex(u32 battler); -u8 CreateBattlerHealthboxSprites(u8 battler); +enum BattleCoordTypes GetBattlerCoordsIndex(enum BattlerId battler); +u8 CreateBattlerHealthboxSprites(enum BattlerId battler); u8 CreateSafariPlayerHealthboxSprites(void); -void SetBattleBarStruct(u8 battler, u8 healthboxSpriteId, s32 maxVal, s32 oldVal, s32 receivedValue); +void SetBattleBarStruct(enum BattlerId battler, u8 healthboxSpriteId, s32 maxVal, s32 oldVal, s32 receivedValue); void SetHealthboxSpriteInvisible(u8 healthboxSpriteId); void SetHealthboxSpriteVisible(u8 healthboxSpriteId); void DummyBattleInterfaceFunc(u8 healthboxSpriteId, bool8 isDoubleBattleBattlerOnly); void UpdateOamPriorityInAllHealthboxes(u8 priority, bool32 hideHpBoxes); -void InitBattlerHealthboxCoords(u8 battler); -void GetBattlerHealthboxCoords(u8 battler, s16 *x, s16 *y); +void InitBattlerHealthboxCoords(enum BattlerId battler); +void GetBattlerHealthboxCoords(enum BattlerId battler, s16 *x, s16 *y); void UpdateHpTextInHealthbox(u32 healthboxSpriteId, u32 maxOrCurrent, s16 currHp, s16 maxHp); void SwapHpBarsWithHpText(void); u8 CreatePartyStatusSummarySprites(enum BattlerId battler, struct HpAndStatus *partyInfo, bool8 skipPlayer, bool8 isBattleStart); void Task_HidePartyStatusSummary(u8 taskId); void UpdateHealthboxAttribute(u8 healthboxSpriteId, struct Pokemon *mon, u8 elementId); -s32 MoveBattleBar(u8 battler, u8 healthboxSpriteId, u8 whichBar, u8 unused); +s32 MoveBattleBar(enum BattlerId battler, u8 healthboxSpriteId, u8 whichBar, u8 unused); u8 GetScaledHPFraction(s16 hp, s16 maxhp, u8 scale); u8 GetHPBarLevel(s16 hp, s16 maxhp); -void CreateAbilityPopUp(u8 battlerId, enum Ability ability, bool32 isDoubleBattle); -void DestroyAbilityPopUp(u8 battlerId); +void CreateAbilityPopUp(enum BattlerId battlerId, enum Ability ability, bool32 isDoubleBattle); +void DestroyAbilityPopUp(enum BattlerId battlerId); bool32 CanThrowLastUsedBall(void); void TryHideLastUsedBall(void); void TryRestoreLastUsedBall(void); void TryAddLastUsedBallItemSprites(void); void SwapBallToDisplay(bool32 sameBall); void ArrowsChangeColorLastBallCycle(bool32 showArrows); -void UpdateAbilityPopup(u8 battlerId); +void UpdateAbilityPopup(enum BattlerId battlerId); void CategoryIcons_LoadSpritesGfx(void); void TryToAddMoveInfoWindow(void); void TryToHideMoveInfoWindow(void); - -// frlg -void UpdateNickInHealthbox(u8 spriteId, struct Pokemon *mon); -void TryAddPokeballIconToHealthbox(u8 spriteId, u8); +void TryAddPokeballIconToHealthbox(u8 healthboxSpriteId, bool8 noStatus); +void UpdateNickInHealthbox(u8 healthboxSpriteId, struct Pokemon *mon); #endif // GUARD_BATTLE_INTERFACE_H diff --git a/include/battle_message.h b/include/battle_message.h index 6e2857f2f..a2b76f80b 100644 --- a/include/battle_message.h +++ b/include/battle_message.h @@ -293,6 +293,9 @@ extern const u8 gText_BattleYesNoChoice[]; extern const u8 gText_SafariBalls[]; extern const u8 gText_HighlightRed_Left[]; +extern const u8 gText_HealthboxGender_Male[]; +extern const u8 gText_HealthboxGender_Female[]; +extern const u8 gText_HealthboxGender_None[]; extern const u8 gText_Win[]; extern const u8 gText_Loss[]; diff --git a/include/graphics.h b/include/graphics.h index c7226855c..031ec5961 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -5170,10 +5170,10 @@ extern const u32 gHoennTrainerCard_Gfx[]; extern const u32 gBattleTextboxTiles[]; extern const u16 gBattleTextboxPalette[]; extern const u32 gBattleTextboxTilemap[]; -extern const u32 gBattleInterface_PartySummaryBar_Gfx[]; +extern const u32 gBattleInterface_BallStatusBarGfx[]; extern const u8 gHealthboxElementsGfxTable[][32]; -extern const u16 gBattleInterface_Healthbox_Pal[]; -extern const u16 gBattleInterface_Healthbar_Pal[]; +extern const u16 gBattleInterface_BallStatusBarPal[]; +extern const u16 gBattleInterface_BallDisplayPal[]; extern const u16 gCategoryIcons_Pal[]; extern const u32 gCategoryIcons_Gfx[]; diff --git a/include/text.h b/include/text.h index ac8f292f9..4cfb5ae33 100644 --- a/include/text.h +++ b/include/text.h @@ -196,6 +196,10 @@ extern const u8 gKeypadIconTiles[]; void DeactivateAllTextPrinters(void); void DeactivateSingleTextPrinter(u32 id, enum TextPrinterType type); u16 AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16)); +u16 AddSpriteTextPrinterParametrerized(u8 spriteId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16)); +void AddSpriteTextPrinterParameterized3(u8 spriteId, u8 fontId, u8 left, u8 top, const u8 *color, s8 speed, const u8 *str); +void AddSpriteTextPrinterParameterized4(u8 spriteId, u8 fontId, u8 left, u8 top, u8 letterSpacing, u8 lineSpacing, const u8 *color, s8 speed, const u8 *str); +void AddSpriteTextPrinterParameterized6(u8 spriteId, u8 fontId, u8 left, u8 top, u8 letterSpacing, u8 lineSpacing, const union TextColor color, s8 speed, const u8 *str); bool32 AddTextPrinter(struct TextPrinterTemplate *textSubPrinter, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16)); void RunTextPrinters(void); bool32 IsTextPrinterActiveOnWindow(u32 windowId); diff --git a/include/util.h b/include/util.h index 42701a360..30bf47b7d 100644 --- a/include/util.h +++ b/include/util.h @@ -5,6 +5,8 @@ #include "sprite.h" +#define HP_EMPTY 0 + extern const u8 gMiscBlank_Gfx[]; // unused in Emerald u8 CreateInvisibleSpriteWithCallback(void (*)(struct Sprite *)); @@ -17,5 +19,6 @@ u32 CalcByteArraySum(const u8 *data, u32 length); void BlendPalette(u16 palOffset, u16 numEntries, u8 coeff, u32 blendColor); void BlendPalettesAt(u16 * palbuff, u16 blend_pal, u32 coefficient, s32 size); void DoBgAffineSet(struct BgAffineDstData * dest, u32 texX, u32 texY, s16 srcX, s16 srcY, s16 sx, s16 sy, u16 alpha); +s32 SubtractClamped(s32 lowestVal, s32 highestVal, s32 currentVal, s32 delta); #endif // GUARD_UTIL_H diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 5186f07d7..999a4af8a 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -115,11 +115,11 @@ static const struct CompressedSpriteSheet sSpriteSheets_HealthBar[MAX_BATTLERS_C const struct SpritePalette sSpritePalettes_HealthBoxHealthBar[2] = { { - .data = gBattleInterface_Healthbox_Pal, + .data = gBattleInterface_BallStatusBarPal, .tag = TAG_HEALTHBOX_PAL, }, { - .data = gBattleInterface_Healthbar_Pal, + .data = gBattleInterface_BallDisplayPal, .tag = TAG_HEALTHBAR_PAL, }, }; @@ -787,7 +787,6 @@ bool8 BattleLoadAllHealthBoxesGfx(u8 state) { LoadSpritePalette(&sSpritePalettes_HealthBoxHealthBar[0]); LoadSpritePalette(&sSpritePalettes_HealthBoxHealthBar[1]); - LoadIndicatorSpritesGfx(); CategoryIcons_LoadSpritesGfx(); } else if (!IsDoubleBattle()) diff --git a/src/battle_gimmick.c b/src/battle_gimmick.c index 26d189efe..d331850d0 100644 --- a/src/battle_gimmick.c +++ b/src/battle_gimmick.c @@ -371,10 +371,10 @@ void UpdateIndicatorLevelData(u32 healthboxId, u32 level) static const s8 sIndicatorPositions[][2] = { - [B_POSITION_PLAYER_LEFT] = {49, -9}, - [B_POSITION_OPPONENT_LEFT] = {40, -9}, - [B_POSITION_PLAYER_RIGHT] = {48, -9}, - [B_POSITION_OPPONENT_RIGHT] = {40, -9}, + [B_POSITION_PLAYER_LEFT] = {48, -9}, + [B_POSITION_OPPONENT_LEFT] = {39, -9}, + [B_POSITION_PLAYER_RIGHT] = {47, -9}, + [B_POSITION_OPPONENT_RIGHT] = {39, -9}, }; void CreateIndicatorSprite(enum BattlerId battler) diff --git a/src/battle_interface.c b/src/battle_interface.c index 2f60f80d3..84666fb3b 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -1,184 +1,201 @@ #include "global.h" -#include "gflib.h" -#include "battle_anim.h" -#include "battle_debug.h" +#include "malloc.h" +#include "battle.h" +#include "pokemon.h" +#include "battle_controllers.h" #include "battle_interface.h" -#include "battle_message.h" #include "battle_z_move.h" -#include "decompress.h" #include "graphics.h" +#include "sprite.h" +#include "window.h" +#include "string_util.h" +#include "text.h" +#include "sound.h" +#include "decompress.h" +#include "task.h" +#include "util.h" +#include "gpu_regs.h" +#include "battle_message.h" +#include "pokedex.h" +#include "palette.h" +#include "international_string_util.h" +#include "safari_zone.h" +#include "battle_anim.h" +#include "data.h" +#include "pokemon_summary_screen.h" +#include "strings.h" +#include "battle_debug.h" #include "item.h" #include "item_icon.h" #include "item_use.h" -#include "menu.h" -#include "pokedex.h" -#include "pokemon_summary_screen.h" -#include "safari_zone.h" #include "test_runner.h" -#include "util.h" +#include "constants/battle_anim.h" +#include "constants/rgb.h" #include "constants/songs.h" +#include "constants/items.h" +#include "caps.h" -#undef abs -#define abs(a) ((a) < 0 ? -(a) : (a)) +#define HEALTHBOX_BG_INDEX 2 -// These are used as indexes for each "section of tiles" in gBattleInterface_Gfx enum -{ - B_INTERFACE_GFX_TRANSPARENT, - B_INTERFACE_GFX_HP_BAR_HP_TEXT, - B_INTERFACE_GFX_HP_BAR_HP_TEXT_2, - B_INTERFACE_GFX_HP_BAR_GREEN, - B_INTERFACE_GFX_HP_BAR_GREEN_2, - B_INTERFACE_GFX_HP_BAR_GREEN_3, - B_INTERFACE_GFX_HP_BAR_GREEN_4, - B_INTERFACE_GFX_HP_BAR_GREEN_5, - B_INTERFACE_GFX_HP_BAR_GREEN_6, - B_INTERFACE_GFX_HP_BAR_GREEN_7, - B_INTERFACE_GFX_HP_BAR_GREEN_8, - B_INTERFACE_GFX_HP_BAR_GREEN_9, - B_INTERFACE_GFX_EXP_BAR, - B_INTERFACE_GFX_EXP_BAR_2, - B_INTERFACE_GFX_EXP_BAR_3, - B_INTERFACE_GFX_EXP_BAR_4, - B_INTERFACE_GFX_EXP_BAR_5, - B_INTERFACE_GFX_EXP_BAR_6, - B_INTERFACE_GFX_EXP_BAR_7, - B_INTERFACE_GFX_EXP_BAR_8, - B_INTERFACE_GFX_EXP_BAR_9, - B_INTERFACE_GFX_STATUS_PSN_BATTLER0, // BATTLER0: B_POSITION_PLAYER_LEFT - B_INTERFACE_GFX_STATUS_PSN_BATTLER0_2, - B_INTERFACE_GFX_STATUS_PSN_BATTLER0_3, - B_INTERFACE_GFX_STATUS_PAR_BATTLER0, - B_INTERFACE_GFX_STATUS_PAR_BATTLER0_2, - B_INTERFACE_GFX_STATUS_PAR_BATTLER0_3, - B_INTERFACE_GFX_STATUS_SLP_BATTLER0, - B_INTERFACE_GFX_STATUS_SLP_BATTLER0_2, - B_INTERFACE_GFX_STATUS_SLP_BATTLER0_3, - B_INTERFACE_GFX_STATUS_FRZ_BATTLER0, - B_INTERFACE_GFX_STATUS_FRZ_BATTLER0_2, - B_INTERFACE_GFX_STATUS_FRZ_BATTLER0_3, - B_INTERFACE_GFX_STATUS_BRN_BATTLER0, - B_INTERFACE_GFX_STATUS_BRN_BATTLER0_2, - B_INTERFACE_GFX_STATUS_BRN_BATTLER0_3, - B_INTERFACE_GFX_STATUS_FRB_BATTLER0, - B_INTERFACE_GFX_STATUS_FRB_BATTLER0_2, - B_INTERFACE_GFX_STATUS_FRB_BATTLER0_3, - B_INTERFACE_GFX_UNUSED_0, - B_INTERFACE_GFX_UNUSED_1, - B_INTERFACE_GFX_UNUSED_2, - B_INTERFACE_GFX_STATUS_NONE, - B_INTERFACE_GFX_UNUSED_3, - B_INTERFACE_GFX_UNUSED_4, - B_INTERFACE_GFX_UNUSED_5, - B_INTERFACE_GFX_SAFARI_HEALTHBOX_0, - B_INTERFACE_GFX_SAFARI_HEALTHBOX_1, - B_INTERFACE_GFX_SAFARI_HEALTHBOX_2, - B_INTERFACE_GFX_UNUSED_6, - B_INTERFACE_GFX_HP_BAR_YELLOW, - B_INTERFACE_GFX_HP_BAR_YELLOW_2, - B_INTERFACE_GFX_HP_BAR_YELLOW_3, - B_INTERFACE_GFX_HP_BAR_YELLOW_4, - B_INTERFACE_GFX_HP_BAR_YELLOW_5, - B_INTERFACE_GFX_HP_BAR_YELLOW_6, - B_INTERFACE_GFX_HP_BAR_YELLOW_7, - B_INTERFACE_GFX_HP_BAR_YELLOW_8, - B_INTERFACE_GFX_HP_BAR_YELLOW_9, - B_INTERFACE_GFX_HP_BAR_RED, - B_INTERFACE_GFX_HP_BAR_RED_2, - B_INTERFACE_GFX_HP_BAR_RED_3, - B_INTERFACE_GFX_HP_BAR_RED_4, - B_INTERFACE_GFX_HP_BAR_RED_5, - B_INTERFACE_GFX_HP_BAR_RED_6, - B_INTERFACE_GFX_HP_BAR_RED_7, - B_INTERFACE_GFX_HP_BAR_RED_8, - B_INTERFACE_GFX_HP_BAR_RED_9, - B_INTERFACE_GFX_HP_BAR_LEFT_BORDER, // Used in place of the HP text graphic if the pokemon is statused - B_INTERFACE_GFX_BALL_PARTY_SUMMARY, - B_INTERFACE_GFX_BALL_PARTY_SUMMARY_2, - B_INTERFACE_GFX_BALL_PARTY_SUMMARY_3, - B_INTERFACE_GFX_BALL_PARTY_SUMMARY_4, - B_INTERFACE_GFX_BALL_CAUGHT, - B_INTERFACE_GFX_STATUS_PSN_BATTLER1, // BATTLER1: B_POSITION_OPPONENT_LEFT - B_INTERFACE_GFX_STATUS_PSN_BATTLER1_2, - B_INTERFACE_GFX_STATUS_PSN_BATTLER1_3, - B_INTERFACE_GFX_STATUS_PAR_BATTLER1, - B_INTERFACE_GFX_STATUS_PAR_BATTLER1_2, - B_INTERFACE_GFX_STATUS_PAR_BATTLER1_3, - B_INTERFACE_GFX_STATUS_SLP_BATTLER1, - B_INTERFACE_GFX_STATUS_SLP_BATTLER1_2, - B_INTERFACE_GFX_STATUS_SLP_BATTLER1_3, - B_INTERFACE_GFX_STATUS_FRZ_BATTLER1, - B_INTERFACE_GFX_STATUS_FRZ_BATTLER1_2, - B_INTERFACE_GFX_STATUS_FRZ_BATTLER1_3, - B_INTERFACE_GFX_STATUS_BRN_BATTLER1, - B_INTERFACE_GFX_STATUS_BRN_BATTLER1_2, - B_INTERFACE_GFX_STATUS_BRN_BATTLER1_3, - B_INTERFACE_GFX_STATUS_FRB_BATTLER1, - B_INTERFACE_GFX_STATUS_FRB_BATTLER1_2, - B_INTERFACE_GFX_STATUS_FRB_BATTLER1_3, - B_INTERFACE_GFX_STATUS_PSN_BATTLER2, // BATTLER2: B_POSITION_PLAYER_RIGHT - B_INTERFACE_GFX_STATUS_PSN_BATTLER2_2, - B_INTERFACE_GFX_STATUS_PSN_BATTLER2_3, - B_INTERFACE_GFX_STATUS_PAR_BATTLER2, - B_INTERFACE_GFX_STATUS_PAR_BATTLER2_2, - B_INTERFACE_GFX_STATUS_PAR_BATTLER2_3, - B_INTERFACE_GFX_STATUS_SLP_BATTLER2, - B_INTERFACE_GFX_STATUS_SLP_BATTLER2_2, - B_INTERFACE_GFX_STATUS_SLP_BATTLER2_3, - B_INTERFACE_GFX_STATUS_FRZ_BATTLER2, - B_INTERFACE_GFX_STATUS_FRZ_BATTLER2_2, - B_INTERFACE_GFX_STATUS_FRZ_BATTLER2_3, - B_INTERFACE_GFX_STATUS_BRN_BATTLER2, - B_INTERFACE_GFX_STATUS_BRN_BATTLER2_2, - B_INTERFACE_GFX_STATUS_BRN_BATTLER2_3, - B_INTERFACE_GFX_STATUS_FRB_BATTLER2, - B_INTERFACE_GFX_STATUS_FRB_BATTLER2_2, - B_INTERFACE_GFX_STATUS_FRB_BATTLER2_3, - B_INTERFACE_GFX_STATUS_PSN_BATTLER3, // BATTLER3: B_POSITION_OPPONENT_RIGHT - B_INTERFACE_GFX_STATUS_PSN_BATTLER3_2, - B_INTERFACE_GFX_STATUS_PSN_BATTLER3_3, - B_INTERFACE_GFX_STATUS_PAR_BATTLER3, - B_INTERFACE_GFX_STATUS_PAR_BATTLER3_2, - B_INTERFACE_GFX_STATUS_PAR_BATTLER3_3, - B_INTERFACE_GFX_STATUS_SLP_BATTLER3, - B_INTERFACE_GFX_STATUS_SLP_BATTLER3_2, - B_INTERFACE_GFX_STATUS_SLP_BATTLER3_3, - B_INTERFACE_GFX_STATUS_FRZ_BATTLER3, - B_INTERFACE_GFX_STATUS_FRZ_BATTLER3_2, - B_INTERFACE_GFX_STATUS_FRZ_BATTLER3_3, - B_INTERFACE_GFX_STATUS_BRN_BATTLER3, - B_INTERFACE_GFX_STATUS_BRN_BATTLER3_2, - B_INTERFACE_GFX_STATUS_BRN_BATTLER3_3, - B_INTERFACE_GFX_STATUS_FRB_BATTLER3, - B_INTERFACE_GFX_STATUS_FRB_BATTLER3_2, - B_INTERFACE_GFX_STATUS_FRB_BATTLER3_3, - B_INTERFACE_GFX_BOTTOM_RIGHT_CORNER_HP_AS_TEXT, // healthbox in double battles - B_INTERFACE_GFX_BOTTOM_RIGHT_CORNER_HP_AS_BAR, // healthbox in double battles +{ // Corresponds to gHealthboxElementsGfxTable (and the tables after it) in graphics.c + // These are indexes into the tables, which are filled with 8x8 square pixel data. + HEALTHBOX_GFX_0, //hp bar [black section] + HEALTHBOX_GFX_1, //hp bar "H" + HEALTHBOX_GFX_2, //hp bar "P" + HEALTHBOX_GFX_HP_BAR_GREEN, //hp bar [0 pixels] + HEALTHBOX_GFX_4, //hp bar [1 pixels] + HEALTHBOX_GFX_5, //hp bar [2 pixels] + HEALTHBOX_GFX_6, //hp bar [3 pixels] + HEALTHBOX_GFX_7, //hp bar [4 pixels] + HEALTHBOX_GFX_8, //hp bar [5 pixels] + HEALTHBOX_GFX_9, //hp bar [6 pixels] + HEALTHBOX_GFX_10, //hp bar [7 pixels] + HEALTHBOX_GFX_11, //hp bar [8 pixels] + HEALTHBOX_GFX_12, //exp bar [0 pixels] + HEALTHBOX_GFX_13, //exp bar [1 pixels] + HEALTHBOX_GFX_14, //exp bar [2 pixels] + HEALTHBOX_GFX_15, //exp bar [3 pixels] + HEALTHBOX_GFX_16, //exp bar [4 pixels] + HEALTHBOX_GFX_17, //exp bar [5 pixels] + HEALTHBOX_GFX_18, //exp bar [6 pixels] + HEALTHBOX_GFX_19, //exp bar [7 pixels] + HEALTHBOX_GFX_20, //exp bar [8 pixels] + HEALTHBOX_GFX_STATUS_PSN_BATTLER0, //status psn "(P" + HEALTHBOX_GFX_22, //status psn "SN" + HEALTHBOX_GFX_23, //status psn "|)"" + HEALTHBOX_GFX_STATUS_PRZ_BATTLER0, //status prz + HEALTHBOX_GFX_25, + HEALTHBOX_GFX_26, + HEALTHBOX_GFX_STATUS_SLP_BATTLER0, //status slp + HEALTHBOX_GFX_28, + HEALTHBOX_GFX_29, + HEALTHBOX_GFX_STATUS_FRZ_BATTLER0, //status frz + HEALTHBOX_GFX_31, + HEALTHBOX_GFX_32, + HEALTHBOX_GFX_STATUS_BRN_BATTLER0, //status brn + HEALTHBOX_GFX_34, + HEALTHBOX_GFX_35, + HEALTHBOX_GFX_STATUS_FRB_BATTLER0, //status frb + HEALTHBOX_GFX_116, + HEALTHBOX_GFX_117, + HEALTHBOX_GFX_36, //misc [Black section] + HEALTHBOX_GFX_37, //misc [Black section] + HEALTHBOX_GFX_38, //misc [Black section] + HEALTHBOX_GFX_39, //misc [Blank Health Window?] + HEALTHBOX_GFX_40, //misc [Blank Health Window?] + HEALTHBOX_GFX_41, //misc [Blank Health Window?] + HEALTHBOX_GFX_42, //misc [Blank Health Window?] + HEALTHBOX_GFX_43, //misc [Top of Health Window?] + HEALTHBOX_GFX_44, //misc [Top of Health Window?] + HEALTHBOX_GFX_45, //misc [Top of Health Window?] + HEALTHBOX_GFX_46, //misc [Blank Health Window?] + HEALTHBOX_GFX_HP_BAR_YELLOW, //hp bar yellow [0 pixels] + HEALTHBOX_GFX_48, //hp bar yellow [1 pixels] + HEALTHBOX_GFX_49, //hp bar yellow [2 pixels] + HEALTHBOX_GFX_50, //hp bar yellow [3 pixels] + HEALTHBOX_GFX_51, //hp bar yellow [4 pixels] + HEALTHBOX_GFX_52, //hp bar yellow [5 pixels] + HEALTHBOX_GFX_53, //hp bar yellow [6 pixels] + HEALTHBOX_GFX_54, //hp bar yellow [7 pixels] + HEALTHBOX_GFX_55, //hp bar yellow [8 pixels] + HEALTHBOX_GFX_HP_BAR_RED, //hp bar red [0 pixels] + HEALTHBOX_GFX_57, //hp bar red [1 pixels] + HEALTHBOX_GFX_58, //hp bar red [2 pixels] + HEALTHBOX_GFX_59, //hp bar red [3 pixels] + HEALTHBOX_GFX_60, //hp bar red [4 pixels] + HEALTHBOX_GFX_61, //hp bar red [5 pixels] + HEALTHBOX_GFX_62, //hp bar red [6 pixels] + HEALTHBOX_GFX_63, //hp bar red [7 pixels] + HEALTHBOX_GFX_64, //hp bar red [8 pixels] + HEALTHBOX_GFX_65, //hp bar frame end + HEALTHBOX_GFX_STATUS_BALL, // Full + HEALTHBOX_GFX_STATUS_BALL_EMPTY, + HEALTHBOX_GFX_STATUS_BALL_FAINTED, + HEALTHBOX_GFX_STATUS_BALL_STATUSED, + HEALTHBOX_GFX_STATUS_BALL_CAUGHT, + HEALTHBOX_GFX_STATUS_PSN_BATTLER1, //status2 "PSN" + HEALTHBOX_GFX_72, + HEALTHBOX_GFX_73, + HEALTHBOX_GFX_STATUS_PRZ_BATTLER1, //status2 "PRZ" + HEALTHBOX_GFX_75, + HEALTHBOX_GFX_76, + HEALTHBOX_GFX_STATUS_SLP_BATTLER1, //status2 "SLP" + HEALTHBOX_GFX_78, + HEALTHBOX_GFX_79, + HEALTHBOX_GFX_STATUS_FRZ_BATTLER1, //status2 "FRZ" + HEALTHBOX_GFX_81, + HEALTHBOX_GFX_82, + HEALTHBOX_GFX_STATUS_BRN_BATTLER1, //status2 "BRN" + HEALTHBOX_GFX_84, + HEALTHBOX_GFX_85, + HEALTHBOX_GFX_STATUS_FRB_BATTLER1, //status2 "FRB" + HEALTHBOX_GFX_118, + HEALTHBOX_GFX_119, + HEALTHBOX_GFX_STATUS_PSN_BATTLER2, //status3 "PSN" + HEALTHBOX_GFX_87, + HEALTHBOX_GFX_88, + HEALTHBOX_GFX_STATUS_PRZ_BATTLER2, //status3 "PRZ" + HEALTHBOX_GFX_90, + HEALTHBOX_GFX_91, + HEALTHBOX_GFX_STATUS_SLP_BATTLER2, //status3 "SLP" + HEALTHBOX_GFX_93, + HEALTHBOX_GFX_94, + HEALTHBOX_GFX_STATUS_FRZ_BATTLER2, //status3 "FRZ" + HEALTHBOX_GFX_96, + HEALTHBOX_GFX_97, + HEALTHBOX_GFX_STATUS_BRN_BATTLER2, //status3 "BRN" + HEALTHBOX_GFX_99, + HEALTHBOX_GFX_100, + HEALTHBOX_GFX_STATUS_FRB_BATTLER2, //status3 "FRB" + HEALTHBOX_GFX_120, + HEALTHBOX_GFX_121, + HEALTHBOX_GFX_STATUS_PSN_BATTLER3, //status4 "PSN" + HEALTHBOX_GFX_102, + HEALTHBOX_GFX_103, + HEALTHBOX_GFX_STATUS_PRZ_BATTLER3, //status4 "PRZ" + HEALTHBOX_GFX_105, + HEALTHBOX_GFX_106, + HEALTHBOX_GFX_STATUS_SLP_BATTLER3, //status4 "SLP" + HEALTHBOX_GFX_108, + HEALTHBOX_GFX_109, + HEALTHBOX_GFX_STATUS_FRZ_BATTLER3, //status4 "FRZ" + HEALTHBOX_GFX_111, + HEALTHBOX_GFX_112, + HEALTHBOX_GFX_STATUS_BRN_BATTLER3, //status4 "BRN" + HEALTHBOX_GFX_114, + HEALTHBOX_GFX_115, + HEALTHBOX_GFX_STATUS_FRB_BATTLER3, //status4 "FRB" + HEALTHBOX_GFX_122, + HEALTHBOX_GFX_123, + HEALTHBOX_GFX_FRAME_END, + HEALTHBOX_GFX_FRAME_END_BAR, }; +static const u8 *GetHealthboxElementGfxPtr(u8); -static void SpriteCB_HealthBoxOther(struct Sprite *sprite); -static void SpriteCB_HealthBar(struct Sprite *sprite); -static const u8 *GetBattleInterfaceGfxPtr(u8 which); -static void UpdateHpTextInHealthboxInDoubles(u8 healthboxSpriteId, u32 maxOrCurrent, s16 currHp, s16 maxHp); -static void Task_HidePartyStatusSummary_BattleStart_1(u8 taskId); -static void Task_HidePartyStatusSummary_BattleStart_2(u8 taskId); -static void SpriteCB_PartySummaryBar_Exit(struct Sprite *sprite); -static void SpriteCB_PartySummaryBall_Exit(struct Sprite *sprite); -static void Task_HidePartyStatusSummary_DuringBattle(u8 taskId); -static void SpriteCB_PartySummaryBall_OnSwitchout(struct Sprite *sprite); -static void UpdateStatusIconInHealthbox(u8 spriteId); -static void SpriteCB_PartySummaryBar(struct Sprite *sprite); -static void SpriteCB_PartySummaryBall_OnBattleStart(struct Sprite *sprite); -static u8 GetStatusIconForBattlerId(u8 statusElementId, u8 battlerId); -static void MoveBattleBarGraphically(u8 battlerId, u8 whichBar); -static u8 GetScaledExpFraction(s32 oldValue, s32 receivedValue, s32 maxValue, u8 scale); -static u8 CalcBarFilledPixels(s32 maxValue, s32 oldValue, s32 receivedValue, s32 *currValue, u8 *arg4, u8 scale); -static s32 CalcNewBarValue(s32 maxValue, s32 currValue, s32 receivedValue, s32 *arg3, u8 arg4, u16 arg5); -static void SafariTextIntoHealthboxObject(void *dest, u8 *windowTileData, u32 windowWidth); -static u8 *AddTextPrinterAndCreateWindowOnHealthbox(const u8 *str, u32 x, u32 y, u32 *windowId); -static void RemoveWindowOnHealthbox(u32 windowId); -static void TextIntoHealthboxObject(void *dest, u8 *windowTileData, s32 windowWidth); +static void UpdateHpTextInHealthboxInDoubles(u32 healthboxSpriteId, u32 maxOrCurrent, s16 currHp, s16 maxHp); +static void UpdateStatusIconInHealthbox(u8); + +static void FillHealthboxObject(void *, u32, u32); + +static void Task_HidePartyStatusSummary_BattleStart_1(u8); +static void Task_HidePartyStatusSummary_BattleStart_2(u8); +static void Task_HidePartyStatusSummary_DuringBattle(u8); + +static void SpriteCB_HealthBoxOther(struct Sprite *); +static void SpriteCB_HealthBar(struct Sprite *); +static void SpriteCB_StatusSummaryBar_Enter(struct Sprite *); +static void SpriteCB_StatusSummaryBar_Exit(struct Sprite *); +static void SpriteCB_StatusSummaryBalls_Enter(struct Sprite *); +static void SpriteCB_StatusSummaryBalls_Exit(struct Sprite *); +static void SpriteCB_StatusSummaryBalls_OnSwitchout(struct Sprite *); + +static u8 GetStatusIconForBattlerId(u8, enum BattlerId); +static s32 CalcNewBarValue(s32, s32, s32, s32 *, u8, u16); +static u8 GetScaledExpFraction(s32, s32, s32, u8); +static void MoveBattleBarGraphically(enum BattlerId, u8); +static u8 CalcBarFilledPixels(s32, s32, s32, s32 *, u8 *, u8); static void SpriteCb_AbilityPopUp(struct Sprite *); static void Task_FreeAbilityPopUpGfx(u8); @@ -204,15 +221,13 @@ static const struct OamData sOamData_64x32 = .affineParam = 0, }; -static const struct SpriteTemplate sHealthboxPlayerSpriteTemplates[] = +static const struct SpriteTemplate sHealthboxPlayerSpriteTemplates[2] = { - [B_POSITION_PLAYER_LEFT / 2] = { .tileTag = TAG_HEALTHBOX_PLAYER1_TILE, .paletteTag = TAG_HEALTHBOX_PAL, .oam = &sOamData_64x32, }, - [B_POSITION_PLAYER_RIGHT / 2] = { .tileTag = TAG_HEALTHBOX_PLAYER2_TILE, .paletteTag = TAG_HEALTHBOX_PAL, @@ -220,15 +235,13 @@ static const struct SpriteTemplate sHealthboxPlayerSpriteTemplates[] = } }; -static const struct SpriteTemplate sHealthboxOpponentSpriteTemplates[] = +static const struct SpriteTemplate sHealthboxOpponentSpriteTemplates[2] = { - [B_POSITION_OPPONENT_LEFT / 2] = { .tileTag = TAG_HEALTHBOX_OPPONENT1_TILE, .paletteTag = TAG_HEALTHBOX_PAL, .oam = &sOamData_64x32, }, - [B_POSITION_OPPONENT_RIGHT / 2] = { .tileTag = TAG_HEALTHBOX_OPPONENT2_TILE, .paletteTag = TAG_HEALTHBOX_PAL, @@ -260,30 +273,26 @@ static const struct OamData sOamData_Healthbar = .affineParam = 0, }; -static const struct SpriteTemplate sHealthbarSpriteTemplates[] = +static const struct SpriteTemplate sHealthbarSpriteTemplates[MAX_BATTLERS_COUNT] = { - [B_POSITION_PLAYER_LEFT] = { .tileTag = TAG_HEALTHBAR_PLAYER1_TILE, .paletteTag = TAG_HEALTHBAR_PAL, .oam = &sOamData_Healthbar, .callback = SpriteCB_HealthBar }, - [B_POSITION_OPPONENT_LEFT] = { .tileTag = TAG_HEALTHBAR_OPPONENT1_TILE, .paletteTag = TAG_HEALTHBAR_PAL, .oam = &sOamData_Healthbar, .callback = SpriteCB_HealthBar }, - [B_POSITION_PLAYER_RIGHT] = { .tileTag = TAG_HEALTHBAR_PLAYER2_TILE, .paletteTag = TAG_HEALTHBAR_PAL, .oam = &sOamData_Healthbar, .callback = SpriteCB_HealthBar }, - [B_POSITION_OPPONENT_RIGHT] = { .tileTag = TAG_HEALTHBAR_OPPONENT2_TILE, .paletteTag = TAG_HEALTHBAR_PAL, @@ -347,19 +356,18 @@ static const struct Subsprite sHealthBar_Subsprites_Opponent[] = } }; -static const struct SubspriteTable sHealthBar_SubspriteTable[] = +static const struct SubspriteTable sHealthBar_SubspriteTables[] = { [B_SIDE_PLAYER] = {ARRAY_COUNT(sHealthBar_Subsprites_Player), sHealthBar_Subsprites_Player}, - [B_SIDE_OPPONENT] = {ARRAY_COUNT(sHealthBar_Subsprites_Opponent), sHealthBar_Subsprites_Opponent}, + [B_SIDE_OPPONENT] = {ARRAY_COUNT(sHealthBar_Subsprites_Opponent), sHealthBar_Subsprites_Opponent} }; - /* v-- Origin [0 ][1 ][2 ][3 ] 128x8 */ static const struct Subsprite sStatusSummaryBar_Subsprites_Enter[] = { { - .x = -96, + .x = 32 * -3, .y = 0, .shape = SPRITE_SHAPE(32x8), .size = SPRITE_SIZE(32x8), @@ -367,7 +375,7 @@ static const struct Subsprite sStatusSummaryBar_Subsprites_Enter[] = .priority = 1 }, { - .x = -64, + .x = 32 * -2, .y = 0, .shape = SPRITE_SHAPE(32x8), .size = SPRITE_SIZE(32x8), @@ -375,7 +383,7 @@ static const struct Subsprite sStatusSummaryBar_Subsprites_Enter[] = .priority = 1 }, { - .x = -32, + .x = 32 * -1, .y = 0, .shape = SPRITE_SHAPE(32x8), .size = SPRITE_SIZE(32x8), @@ -392,10 +400,14 @@ static const struct Subsprite sStatusSummaryBar_Subsprites_Enter[] = } }; +/* v-- Origin +[0 ][1 ][2 ][3 ][4 ][5 ] 192x8 + ^-- uses same tiles --^ +*/ static const struct Subsprite sStatusSummaryBar_Subsprites_Exit[] = { { - .x = -96, + .x = 32 * -3, .y = 0, .shape = SPRITE_SHAPE(32x8), .size = SPRITE_SIZE(32x8), @@ -403,7 +415,7 @@ static const struct Subsprite sStatusSummaryBar_Subsprites_Exit[] = .priority = 1 }, { - .x = -64, + .x = 32 * -2, .y = 0, .shape = SPRITE_SHAPE(32x8), .size = SPRITE_SIZE(32x8), @@ -411,7 +423,7 @@ static const struct Subsprite sStatusSummaryBar_Subsprites_Exit[] = .priority = 1 }, { - .x = -32, + .x = 32 * -1, .y = 0, .shape = SPRITE_SHAPE(32x8), .size = SPRITE_SIZE(32x8), @@ -419,7 +431,7 @@ static const struct Subsprite sStatusSummaryBar_Subsprites_Exit[] = .priority = 1 }, { - .x = 0, + .x = 32 * 0, .y = 0, .shape = SPRITE_SHAPE(32x8), .size = SPRITE_SIZE(32x8), @@ -427,7 +439,7 @@ static const struct Subsprite sStatusSummaryBar_Subsprites_Exit[] = .priority = 1 }, { - .x = 32, + .x = 32 * 1, .y = 0, .shape = SPRITE_SHAPE(32x8), .size = SPRITE_SIZE(32x8), @@ -435,7 +447,7 @@ static const struct Subsprite sStatusSummaryBar_Subsprites_Exit[] = .priority = 1 }, { - .x = 64, + .x = 32 * 2, .y = 0, .shape = SPRITE_SHAPE(32x8), .size = SPRITE_SIZE(32x8), @@ -456,28 +468,22 @@ static const struct SubspriteTable sStatusSummaryBar_SubspriteTable_Exit[] = static const struct CompressedSpriteSheet sStatusSummaryBarSpriteSheet = { - .data = gBattleInterface_PartySummaryBar_Gfx, - .size = 16 * TILE_SIZE_4BPP, - .tag = TAG_STATUS_SUMMARY_BAR_TILE, + gBattleInterface_BallStatusBarGfx, 0x200, TAG_STATUS_SUMMARY_BAR_TILE }; static const struct SpritePalette sStatusSummaryBarSpritePal = { - .data = gBattleInterface_Healthbox_Pal, - .tag = TAG_STATUS_SUMMARY_BAR_PAL, + gBattleInterface_BallStatusBarPal, TAG_STATUS_SUMMARY_BAR_PAL }; static const struct SpritePalette sStatusSummaryBallsSpritePal = { - .data = gBattleInterface_Healthbar_Pal, - .tag = TAG_STATUS_SUMMARY_BALLS_PAL, + gBattleInterface_BallDisplayPal, TAG_STATUS_SUMMARY_BALLS_PAL }; static const struct SpriteSheet sStatusSummaryBallsSpriteSheet = { - .data = &gHealthboxElementsGfxTable[B_INTERFACE_GFX_BALL_PARTY_SUMMARY], - .size = 4 * TILE_SIZE_4BPP, - .tag = TAG_STATUS_SUMMARY_BALLS_TILE, + &gHealthboxElementsGfxTable[HEALTHBOX_GFX_STATUS_BALL], 0x80, TAG_STATUS_SUMMARY_BALLS_TILE }; static const struct OamData sOamData_StatusSummaryBalls = @@ -497,61 +503,98 @@ static const struct OamData sOamData_StatusSummaryBalls = .affineParam = 0, }; -static const struct SpriteTemplate sStatusSummaryBarSpriteTemplates[] = { - { +static const struct SpriteTemplate sStatusSummaryBarSpriteTemplates[2] = +{ + { // Player .tileTag = TAG_STATUS_SUMMARY_BAR_TILE, .paletteTag = TAG_STATUS_SUMMARY_BAR_PAL, .oam = &sOamData_64x32, - .callback = SpriteCB_PartySummaryBar - }, { + .callback = SpriteCB_StatusSummaryBar_Enter + }, + { // Opponent .tileTag = TAG_STATUS_SUMMARY_BAR_TILE, .paletteTag = TAG_STATUS_SUMMARY_BAR_PAL, .oam = &sOamData_64x32, - .callback = SpriteCB_PartySummaryBar + .callback = SpriteCB_StatusSummaryBar_Enter } }; -static const struct SpriteTemplate sStatusSummaryBallsSpriteTemplates[] = { +static const struct SpriteTemplate sStatusSummaryBallsSpriteTemplates[2] = +{ { .tileTag = TAG_STATUS_SUMMARY_BALLS_TILE, .paletteTag = TAG_STATUS_SUMMARY_BALLS_PAL, .oam = &sOamData_StatusSummaryBalls, - .callback = SpriteCB_PartySummaryBall_OnBattleStart - }, { + .callback = SpriteCB_StatusSummaryBalls_Enter + }, + { .tileTag = TAG_STATUS_SUMMARY_BALLS_TILE, .paletteTag = TAG_STATUS_SUMMARY_BALLS_PAL, .oam = &sOamData_StatusSummaryBalls, - .callback = SpriteCB_PartySummaryBall_OnBattleStart + .callback = SpriteCB_StatusSummaryBalls_Enter } }; -// Because the healthbox is too large to fit into one sprite, it is divided -// into two sprites. The left sprite is used as the 'main' healthbox sprite, -// while the right sprite is the 'other' healthbox sprite. -// There is also a third sprite for the healthbar, visible on the healthbox. - -// sprite data for main (left) healthbox sprite -#define sHealthboxOtherSpriteId oam.affineParam -#define sHealthBarSpriteId data[5] -#define sBattlerId data[6] - -// sprite data for other (right) healthbox sprite -#define sHealthboxSpriteId data[5] - -// sprite data for healthbar sprite -#define sHealthboxSpriteId data[5] -#define sHealthbarType data[6] +static const u8 sEmptyWhiteText_GrayHighlight[] = __("{COLOR WHITE}{BACKGROUND DARK_GRAY}{ACCENT DARK_GRAY} "); +static const u8 sEmptyWhiteText_TransparentHighlight[] = __("{COLOR WHITE}{BACKGROUND TRANSPARENT}{ACCENT TRANSPARENT} "); enum { - HEALTHBAR_TYPE_PLAYER_SINGLE, - HEALTHBAR_TYPE_PLAYER_DOUBLE, - HEALTHBAR_TYPE_OPPONENT, + PAL_STATUS_PSN, + PAL_STATUS_PAR, + PAL_STATUS_SLP, + PAL_STATUS_FRZ, + PAL_STATUS_BRN }; +static const u16 sStatusIconColors[] = +{ + [PAL_STATUS_PSN] = RGB(24, 12, 24), + [PAL_STATUS_PAR] = RGB(23, 23, 3), + [PAL_STATUS_SLP] = RGB(20, 20, 17), + [PAL_STATUS_FRZ] = RGB(17, 22, 28), + [PAL_STATUS_BRN] = RGB(28, 14, 10), +}; + +static const struct WindowTemplate sHealthboxWindowTemplate = { + .bg = 0, + .tilemapLeft = 0, + .tilemapTop = 0, + .width = 8, + .height = 2, + .paletteNum = 0, + .baseBlock = 0 +}; + +static const union TextColor sHealthBoxTextColor = +{ + .background = 0, + .foreground = 1, + .shadow = 3, + .accent = 0 +}; + +// Because the healthbox is too large to fit into one sprite, it is divided into two sprites. +// healthboxLeft or healthboxMain is the left part that is used as the 'main' sprite. +// healthboxRight or healthboxOther is the right part of the healthbox. +// There's also the third sprite under name of healthbarSprite that refers to the healthbar visible on the healtbox. + +// data fields for healthboxMain +// oam.affineParam holds healthboxRight spriteId +#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] +#define hBar_Data6 data[6] + // This function is here to cover a specific case - one player's mon in a 2 vs 1 double battle. In this scenario - display singles layout. // The same goes for a 2 vs 1 where opponent has only one pokemon. -enum BattleCoordTypes GetBattlerCoordsIndex(u32 battler) +enum BattleCoordTypes GetBattlerCoordsIndex(enum BattlerId battler) { if (GetBattlerPosition(battler) == B_POSITION_PLAYER_LEFT && gPlayerPartyCount == 1 && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) return BATTLE_COORDS_SINGLES; @@ -563,102 +606,114 @@ enum BattleCoordTypes GetBattlerCoordsIndex(u32 battler) return BATTLE_COORDS_SINGLES; } -u8 CreateBattlerHealthboxSprites(u8 battlerId) +u8 CreateBattlerHealthboxSprites(enum BattlerId battler) { - s16 healthbarType = HEALTHBAR_TYPE_PLAYER_SINGLE; - u8 healthboxSpriteId; - u8 healthboxOtherSpriteId; + s16 data6 = 0; + u8 healthboxLeftSpriteId, healthboxRightSpriteId; u8 healthbarSpriteId; - struct Sprite *healthbarSprite; + struct Sprite *healthBarSpritePtr; - if (GetBattlerCoordsIndex(battlerId) == 0) + switch (GetBattlerCoordsIndex(battler)) { - if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + default: + case BATTLE_COORDS_SINGLES: + { + if (IsOnPlayerSide(battler)) { - healthboxSpriteId = CreateSprite(&sHealthboxPlayerSpriteTemplates[B_POSITION_PLAYER_LEFT / 2], 240, 160, 1); - healthboxOtherSpriteId = CreateSpriteAtEnd(&sHealthboxPlayerSpriteTemplates[B_POSITION_PLAYER_LEFT / 2], 240, 160, 1); + healthboxLeftSpriteId = CreateSprite(&sHealthboxPlayerSpriteTemplates[0], DISPLAY_WIDTH, DISPLAY_HEIGHT, 1); + healthboxRightSpriteId = CreateSpriteAtEnd(&sHealthboxPlayerSpriteTemplates[0], DISPLAY_WIDTH, DISPLAY_HEIGHT, 1); - gSprites[healthboxSpriteId].oam.shape = SPRITE_SHAPE(64x64); - gSprites[healthboxOtherSpriteId].oam.shape = SPRITE_SHAPE(64x64); - gSprites[healthboxOtherSpriteId].oam.tileNum += 2 * TILE_SIZE_4BPP; + gSprites[healthboxLeftSpriteId].oam.shape = ST_OAM_SQUARE; + + gSprites[healthboxRightSpriteId].oam.shape = ST_OAM_SQUARE; + gSprites[healthboxRightSpriteId].oam.tileNum += 64; } else { - healthboxSpriteId = CreateSprite(&sHealthboxOpponentSpriteTemplates[B_POSITION_OPPONENT_LEFT / 2], 240, 160, 1); - healthboxOtherSpriteId = CreateSpriteAtEnd(&sHealthboxOpponentSpriteTemplates[B_POSITION_OPPONENT_LEFT / 2], 240, 160, 1); + healthboxLeftSpriteId = CreateSprite(&sHealthboxOpponentSpriteTemplates[0], DISPLAY_WIDTH, DISPLAY_HEIGHT, 1); + healthboxRightSpriteId = CreateSpriteAtEnd(&sHealthboxOpponentSpriteTemplates[0], DISPLAY_WIDTH, DISPLAY_HEIGHT, 1); - gSprites[healthboxOtherSpriteId].oam.tileNum += 1 * TILE_SIZE_4BPP; - healthbarType = HEALTHBAR_TYPE_OPPONENT; + gSprites[healthboxRightSpriteId].oam.tileNum += 32; + + data6 = 2; } + gSprites[healthboxLeftSpriteId].oam.affineParam = healthboxRightSpriteId; - gSprites[healthboxSpriteId].sHealthboxOtherSpriteId = healthboxOtherSpriteId; - gSprites[healthboxOtherSpriteId].sHealthboxSpriteId = healthboxSpriteId; - gSprites[healthboxOtherSpriteId].callback = SpriteCB_HealthBoxOther; + gSprites[healthboxRightSpriteId].hOther_HealthBoxSpriteId = healthboxLeftSpriteId; + gSprites[healthboxRightSpriteId].callback = SpriteCB_HealthBoxOther; + break; } - else + case BATTLE_COORDS_DOUBLES: { - if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + if (IsOnPlayerSide(battler)) { - healthboxSpriteId = CreateSprite(&sHealthboxPlayerSpriteTemplates[GetBattlerPosition(battlerId) / 2], 240, 160, 1); - healthboxOtherSpriteId = CreateSpriteAtEnd(&sHealthboxPlayerSpriteTemplates[GetBattlerPosition(battlerId) / 2], 240, 160, 1); - - gSprites[healthboxSpriteId].sHealthboxOtherSpriteId = healthboxOtherSpriteId; - gSprites[healthboxOtherSpriteId].sHealthboxSpriteId = healthboxSpriteId; - gSprites[healthboxOtherSpriteId].oam.tileNum += 1 * TILE_SIZE_4BPP; - gSprites[healthboxOtherSpriteId].callback = SpriteCB_HealthBoxOther; - healthbarType = HEALTHBAR_TYPE_PLAYER_DOUBLE; + healthboxLeftSpriteId = CreateSprite(&sHealthboxPlayerSpriteTemplates[GetBattlerPosition(battler) / 2], DISPLAY_WIDTH, DISPLAY_HEIGHT, 1); + healthboxRightSpriteId = CreateSpriteAtEnd(&sHealthboxPlayerSpriteTemplates[GetBattlerPosition(battler) / 2], DISPLAY_WIDTH, DISPLAY_HEIGHT, 1); + data6 = 1; } else { - healthboxSpriteId = CreateSprite(&sHealthboxOpponentSpriteTemplates[GetBattlerPosition(battlerId) / 2], 240, 160, 1); - healthboxOtherSpriteId = CreateSpriteAtEnd(&sHealthboxOpponentSpriteTemplates[GetBattlerPosition(battlerId) / 2], 240, 160, 1); - - gSprites[healthboxSpriteId].sHealthboxOtherSpriteId = healthboxOtherSpriteId; - gSprites[healthboxOtherSpriteId].sHealthboxSpriteId = healthboxSpriteId; - gSprites[healthboxOtherSpriteId].oam.tileNum += 1 * TILE_SIZE_4BPP; - gSprites[healthboxOtherSpriteId].callback = SpriteCB_HealthBoxOther; - healthbarType = HEALTHBAR_TYPE_OPPONENT; + healthboxLeftSpriteId = CreateSprite(&sHealthboxOpponentSpriteTemplates[GetBattlerPosition(battler) / 2], DISPLAY_WIDTH, DISPLAY_HEIGHT, 1); + healthboxRightSpriteId = CreateSpriteAtEnd(&sHealthboxOpponentSpriteTemplates[GetBattlerPosition(battler) / 2], DISPLAY_WIDTH, DISPLAY_HEIGHT, 1); + data6 = 2; } + gSprites[healthboxLeftSpriteId].oam.affineParam = healthboxRightSpriteId; + + gSprites[healthboxRightSpriteId].hOther_HealthBoxSpriteId = healthboxLeftSpriteId; + gSprites[healthboxRightSpriteId].oam.tileNum += 32; + gSprites[healthboxRightSpriteId].callback = SpriteCB_HealthBoxOther; + break; + } } - healthbarSpriteId = CreateSpriteAtEnd(&sHealthbarSpriteTemplates[gBattlerPositions[battlerId]], 140, 60, 0); - healthbarSprite = &gSprites[healthbarSpriteId]; - SetSubspriteTables(healthbarSprite, &sHealthBar_SubspriteTable[GetBattlerSide(battlerId)]); - healthbarSprite->subspriteMode = SUBSPRITES_IGNORE_PRIORITY; - healthbarSprite->oam.priority = 1; - CpuCopy32(GetBattleInterfaceGfxPtr(B_INTERFACE_GFX_HP_BAR_HP_TEXT), OBJ_VRAM0 + healthbarSprite->oam.tileNum * TILE_SIZE_4BPP, 2 * TILE_SIZE_4BPP); - gSprites[healthboxSpriteId].sHealthBarSpriteId = healthbarSpriteId; - gSprites[healthboxSpriteId].sBattlerId = battlerId; - gSprites[healthboxSpriteId].invisible = TRUE; - gSprites[healthboxOtherSpriteId].invisible = TRUE; - healthbarSprite->sHealthboxSpriteId = healthboxSpriteId; - healthbarSprite->sHealthbarType = healthbarType; - healthbarSprite->invisible = TRUE; + healthbarSpriteId = CreateSpriteAtEnd(&sHealthbarSpriteTemplates[gBattlerPositions[battler]], 140, 60, 0); + healthBarSpritePtr = &gSprites[healthbarSpriteId]; + SetSubspriteTables(healthBarSpritePtr, &sHealthBar_SubspriteTables[GetBattlerSide(battler)]); + healthBarSpritePtr->subspriteMode = SUBSPRITES_IGNORE_PRIORITY; + healthBarSpritePtr->oam.priority = 1; - CreateIndicatorSprite(battlerId); + CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_1), (void *)(OBJ_VRAM0 + healthBarSpritePtr->oam.tileNum * TILE_SIZE_4BPP), 64); + + gSprites[healthboxLeftSpriteId].hMain_HealthBarSpriteId = healthbarSpriteId; + gSprites[healthboxLeftSpriteId].hMain_Battler = battler; + gSprites[healthboxLeftSpriteId].invisible = TRUE; + + gSprites[healthboxRightSpriteId].invisible = TRUE; + + healthBarSpritePtr->hBar_HealthBoxSpriteId = healthboxLeftSpriteId; + healthBarSpritePtr->hBar_Data6 = data6; + healthBarSpritePtr->invisible = TRUE; + + CreateIndicatorSprite(battler); gBattleStruct->ballSpriteIds[0] = MAX_SPRITES; gBattleStruct->ballSpriteIds[1] = MAX_SPRITES; gBattleStruct->moveInfoSpriteId = MAX_SPRITES; - return healthboxSpriteId; + return healthboxLeftSpriteId; } u8 CreateSafariPlayerHealthboxSprites(void) { - u8 healthboxSpriteId = CreateSprite(&sHealthboxSafariSpriteTemplate, 240, 160, 1); - u8 healthboxOtherSpriteId = CreateSpriteAtEnd(&sHealthboxSafariSpriteTemplate, 240, 160, 1); + u8 healthboxLeftSpriteId, healthboxRightSpriteId; - gSprites[healthboxSpriteId].oam.shape = SPRITE_SHAPE(64x64); - gSprites[healthboxOtherSpriteId].oam.shape = SPRITE_SHAPE(64x64); - gSprites[healthboxOtherSpriteId].oam.tileNum += 2 * TILE_SIZE_4BPP; - gSprites[healthboxSpriteId].sHealthboxOtherSpriteId = healthboxOtherSpriteId; - gSprites[healthboxOtherSpriteId].sHealthboxSpriteId = healthboxSpriteId; - gSprites[healthboxOtherSpriteId].callback = SpriteCB_HealthBoxOther; - return healthboxSpriteId; + healthboxLeftSpriteId = CreateSprite(&sHealthboxSafariSpriteTemplate, DISPLAY_WIDTH, DISPLAY_HEIGHT, 1); + healthboxRightSpriteId = CreateSpriteAtEnd(&sHealthboxSafariSpriteTemplate, DISPLAY_WIDTH, DISPLAY_HEIGHT, 1); + + gSprites[healthboxLeftSpriteId].oam.shape = ST_OAM_SQUARE; + gSprites[healthboxRightSpriteId].oam.shape = ST_OAM_SQUARE; + + gSprites[healthboxRightSpriteId].oam.tileNum += 64; + + gSprites[healthboxLeftSpriteId].oam.affineParam = healthboxRightSpriteId; + gSprites[healthboxRightSpriteId].hOther_HealthBoxSpriteId = healthboxLeftSpriteId; + + gSprites[healthboxRightSpriteId].callback = SpriteCB_HealthBoxOther; + + return healthboxLeftSpriteId; } -static const u8 *GetBattleInterfaceGfxPtr(u8 elementId) +static const u8 *GetHealthboxElementGfxPtr(u8 elementId) { return gHealthboxElementsGfxTable[elementId]; } @@ -666,61 +721,62 @@ static const u8 *GetBattleInterfaceGfxPtr(u8 elementId) // Syncs the position of healthbar accordingly with the healthbox. static void SpriteCB_HealthBar(struct Sprite *sprite) { - u8 healthboxSpriteId = sprite->sHealthboxSpriteId; + u8 healthboxSpriteId = sprite->hBar_HealthBoxSpriteId; - switch (sprite->sHealthbarType) + switch (sprite->hBar_Data6) { - case HEALTHBAR_TYPE_PLAYER_SINGLE: + case 0: sprite->x = gSprites[healthboxSpriteId].x + 16; sprite->y = gSprites[healthboxSpriteId].y; break; - case HEALTHBAR_TYPE_PLAYER_DOUBLE: + case 1: sprite->x = gSprites[healthboxSpriteId].x + 16; sprite->y = gSprites[healthboxSpriteId].y; break; + case 2: default: - case HEALTHBAR_TYPE_OPPONENT: sprite->x = gSprites[healthboxSpriteId].x + 8; sprite->y = gSprites[healthboxSpriteId].y; break; } + sprite->x2 = gSprites[healthboxSpriteId].x2; sprite->y2 = gSprites[healthboxSpriteId].y2; } static void SpriteCB_HealthBoxOther(struct Sprite *sprite) { - u8 healthboxSpriteId = sprite->sHealthboxSpriteId; + u8 healthboxMainSpriteId = sprite->hOther_HealthBoxSpriteId; - sprite->x = gSprites[healthboxSpriteId].x + 64; - sprite->y = gSprites[healthboxSpriteId].y; + sprite->x = gSprites[healthboxMainSpriteId].x + 64; + sprite->y = gSprites[healthboxMainSpriteId].y; - sprite->x2 = gSprites[healthboxSpriteId].x2; - sprite->y2 = gSprites[healthboxSpriteId].y2; + sprite->x2 = gSprites[healthboxMainSpriteId].x2; + sprite->y2 = gSprites[healthboxMainSpriteId].y2; } -void SetBattleBarStruct(u8 battlerId, u8 healthboxSpriteId, s32 maxVal, s32 oldVal, s32 receivedValue) +void SetBattleBarStruct(enum BattlerId battler, u8 healthboxSpriteId, s32 maxVal, s32 oldVal, s32 receivedValue) { - gBattleSpritesDataPtr->battleBars[battlerId].healthboxSpriteId = healthboxSpriteId; - gBattleSpritesDataPtr->battleBars[battlerId].maxValue = maxVal; - gBattleSpritesDataPtr->battleBars[battlerId].oldValue = oldVal; - gBattleSpritesDataPtr->battleBars[battlerId].receivedValue = receivedValue; - gBattleSpritesDataPtr->battleBars[battlerId].currValue = -32768; + gBattleSpritesDataPtr->battleBars[battler].healthboxSpriteId = healthboxSpriteId; + gBattleSpritesDataPtr->battleBars[battler].maxValue = maxVal; + gBattleSpritesDataPtr->battleBars[battler].oldValue = oldVal; + gBattleSpritesDataPtr->battleBars[battler].receivedValue = receivedValue; + gBattleSpritesDataPtr->battleBars[battler].currValue = -32768; } void SetHealthboxSpriteInvisible(u8 healthboxSpriteId) { gSprites[healthboxSpriteId].invisible = TRUE; - gSprites[gSprites[healthboxSpriteId].sHealthBarSpriteId].invisible = TRUE; - gSprites[gSprites[healthboxSpriteId].sHealthboxOtherSpriteId].invisible = TRUE; + gSprites[gSprites[healthboxSpriteId].hMain_HealthBarSpriteId].invisible = TRUE; + gSprites[gSprites[healthboxSpriteId].oam.affineParam].invisible = TRUE; UpdateIndicatorVisibilityAndType(healthboxSpriteId, TRUE); } void SetHealthboxSpriteVisible(u8 healthboxSpriteId) { gSprites[healthboxSpriteId].invisible = FALSE; - gSprites[gSprites[healthboxSpriteId].sHealthBarSpriteId].invisible = FALSE; - gSprites[gSprites[healthboxSpriteId].sHealthboxOtherSpriteId].invisible = FALSE; + gSprites[gSprites[healthboxSpriteId].hMain_HealthBarSpriteId].invisible = FALSE; + gSprites[gSprites[healthboxSpriteId].oam.affineParam].invisible = FALSE; UpdateIndicatorVisibilityAndType(healthboxSpriteId, FALSE); } @@ -730,15 +786,9 @@ static void UpdateSpritePos(u8 spriteId, s16 x, s16 y) gSprites[spriteId].y = y; } -void DestoryHealthboxSprite(u8 healthboxSpriteId) -{ - DestroySprite(&gSprites[gSprites[healthboxSpriteId].sHealthboxOtherSpriteId]); - DestroySprite(&gSprites[gSprites[healthboxSpriteId].sHealthBarSpriteId]); - DestroySprite(&gSprites[healthboxSpriteId]); -} - void DummyBattleInterfaceFunc(u8 healthboxSpriteId, bool8 isDoubleBattleBattlerOnly) { + } static void TryToggleHealboxVisibility(u32 priority, u32 healthboxLeftSpriteId, u32 healthboxRightSpriteId, u32 healthbarSpriteId) @@ -759,13 +809,11 @@ static void TryToggleHealboxVisibility(u32 priority, u32 healthboxLeftSpriteId, void UpdateOamPriorityInAllHealthboxes(u8 priority, bool32 hideHPBoxes) { - s32 i; - - for (i = 0; i < gBattlersCount; i++) + for (enum BattlerId i = 0; i < gBattlersCount; i++) { u8 healthboxLeftSpriteId = gHealthboxSpriteIds[i]; u8 healthboxRightSpriteId = gSprites[gHealthboxSpriteIds[i]].oam.affineParam; - u8 healthbarSpriteId = gSprites[gHealthboxSpriteIds[i]].sHealthBarSpriteId; + u8 healthbarSpriteId = gSprites[gHealthboxSpriteIds[i]].hMain_HealthBarSpriteId; gSprites[healthboxLeftSpriteId].oam.priority = priority; gSprites[healthboxRightSpriteId].oam.priority = priority; @@ -794,7 +842,7 @@ static const s16 sBattlerHealthboxCoords[BATTLE_COORDS_COUNT][MAX_BATTLERS_COUNT }, }; -void GetBattlerHealthboxCoords(u8 battler, s16 *x, s16 *y) +void GetBattlerHealthboxCoords(enum BattlerId battler, s16 *x, s16 *y) { enum BattlerPosition position = GetBattlerPosition(battler); enum BattleCoordTypes index = GetBattlerCoordsIndex(battler); @@ -803,7 +851,7 @@ void GetBattlerHealthboxCoords(u8 battler, s16 *x, s16 *y) *y = sBattlerHealthboxCoords[index][position][1]; } -void InitBattlerHealthboxCoords(u8 battler) +void InitBattlerHealthboxCoords(enum BattlerId battler) { s16 x, y; @@ -813,18 +861,14 @@ void InitBattlerHealthboxCoords(u8 battler) static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl) { - u32 windowId, spriteTileNum; - u8 *windowTileData; u8 text[16]; - u32 xPos; - u8 *objVram; - u8 battler = gSprites[healthboxSpriteId].sBattlerId; + enum BattlerId battler = gSprites[healthboxSpriteId].hMain_Battler; + u32 spriteId = gSprites[healthboxSpriteId].oam.affineParam; // Don't print Lv char if mon has a gimmick with an indicator active. if (GetIndicatorPalTag(battler) != TAG_NONE) { - objVram = ConvertIntToDecimalStringN(text, lvl, STR_CONV_MODE_LEFT_ALIGN, 3); - xPos = 5 * (3 - (objVram - (text + 2))) - 1; + ConvertIntToDecimalStringN(text, lvl, STR_CONV_MODE_LEFT_ALIGN, 3); UpdateIndicatorLevelData(healthboxSpriteId, lvl); UpdateIndicatorVisibilityAndType(healthboxSpriteId, FALSE); } @@ -833,208 +877,212 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl) text[0] = CHAR_EXTRA_SYMBOL; text[1] = CHAR_LV_2; - objVram = ConvertIntToDecimalStringN(text + 2, lvl, STR_CONV_MODE_LEFT_ALIGN, 3); - xPos = 5 * (3 - (objVram - (text + 2))); + ConvertIntToDecimalStringN(text + 2, lvl, STR_CONV_MODE_LEFT_ALIGN, 3); UpdateIndicatorVisibilityAndType(healthboxSpriteId, TRUE); } - windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, xPos, 3, &windowId); - spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * TILE_SIZE_4BPP; + u32 width = GetStringWidth(FONT_SMALL, text, 0); if (IsOnPlayerSide(battler)) { - objVram = (void *)(OBJ_VRAM0); - switch (GetBattlerCoordsIndex(battler)) - { - case BATTLE_COORDS_SINGLES: - objVram += spriteTileNum + 0x820; - break; - default: - objVram += spriteTileNum + 0x420; - break; - } + FillSpriteRectColor(spriteId, 8, 5, 24, 11, HEALTHBOX_BG_INDEX); + AddSpriteTextPrinterParameterized6(spriteId, FONT_SMALL, 31 - width, 3, 0, 0, sHealthBoxTextColor, 0, text); } else { - objVram = (void *)(OBJ_VRAM0); - objVram += spriteTileNum + 0x400; + FillSpriteRectColor(spriteId, 0, 5, 24, 11, HEALTHBOX_BG_INDEX); + AddSpriteTextPrinterParameterized6(spriteId, FONT_SMALL, 23 - width, 3, 0, 0, sHealthBoxTextColor, 0, text); } - TextIntoHealthboxObject(objVram, windowTileData, 3); - RemoveWindowOnHealthbox(windowId); } -void UpdateHpTextInHealthbox(u32 healthboxSpriteId, u32 maxOrCurrent, s16 currHp, s16 maxHp) -{ - u32 windowId, spriteTileNum; - u8 *windowTileData; +#define HP_FONT FONT_SMALL +#define HP_MAX_DIGITS 4 +#define HP_RIGHT_SPRITE_CHARS 6 - if (GetBattlerSide(gSprites[healthboxSpriteId].sBattlerId) == B_SIDE_PLAYER && !GetBattlerCoordsIndex(gSprites[healthboxSpriteId].sBattlerId)) - { - // Only in the Japanese release can HP be displayed as text outside of double battles - u8 text[8]; - if (maxOrCurrent != HP_CURRENT) // singles, max - { - ConvertIntToDecimalStringN(text, maxHp, STR_CONV_MODE_RIGHT_ALIGN, 3); - windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, 0, 5, &windowId); - spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum; - TextIntoHealthboxObject((void *)(OBJ_VRAM0) + spriteTileNum * TILE_SIZE_4BPP + 0xA40, windowTileData, 2); - RemoveWindowOnHealthbox(windowId); - } - else // singles, current - { - u8 *strptr; - strptr = ConvertIntToDecimalStringN(text, currHp, STR_CONV_MODE_RIGHT_ALIGN, 3); - *strptr++ = CHAR_SLASH; - *strptr++ = EOS; - windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, 4, 5, &windowId); - spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum; - TextIntoHealthboxObject((void *)(OBJ_VRAM0) + spriteTileNum * TILE_SIZE_4BPP + 0x2E0, windowTileData, 1); - TextIntoHealthboxObject((void *)(OBJ_VRAM0) + spriteTileNum * TILE_SIZE_4BPP + 0xA00, windowTileData + 0x20, 2); - RemoveWindowOnHealthbox(windowId); - } - } +static void PrintHpOnHealthbox(u32 spriteId, s16 currHp, s16 maxHp, u32 bgColor, u8 yOffset) +{ + u32 width; + u8 text[2 * HP_MAX_DIGITS + 2], *txtPtr; + + // To fit 4 digit HP values we need to modify a bit the way hp is printed on Healthbox. + // HP_RIGHT_SPRITE_CHARS chars can fit on the right healthbox, the rest goes to the left one + txtPtr = ConvertIntToDecimalStringN(text, currHp, STR_CONV_MODE_RIGHT_ALIGN, HP_MAX_DIGITS); + *txtPtr++ = CHAR_SLASH; + txtPtr = ConvertIntToDecimalStringN(txtPtr, maxHp, STR_CONV_MODE_LEFT_ALIGN, HP_MAX_DIGITS); + + u32 spriteId2 = gSprites[spriteId].oam.affineParam; + + // Don't assume that healthbox sprites don't have data in the fields used for sprite printing + // and set up temporary values with what's needed + s16 savedValue1 = gSprites[spriteId].data[1]; + s16 savedValue2 = gSprites[spriteId2].data[1]; + gSprites[spriteId].data[1] = spriteId2; + gSprites[spriteId2].data[1] = SPRITE_NONE; + + // Clear out old text first + FillSpriteRectColor(spriteId, 40, yOffset + 8, 56, 8, bgColor); + + width = GetStringWidth(HP_FONT, text, -1) + GetFontAttribute(HP_FONT, FONTATTR_LETTER_SPACING); + if (width < 31) + AddSpriteTextPrinterParameterized6(spriteId2, HP_FONT, 31 - width, yOffset + 5, 0, 0, sHealthBoxTextColor, 0, text); else - { - u8 battler; + AddSpriteTextPrinterParameterized6(spriteId, HP_FONT, 63 - (width - 32), yOffset + 5, 0, 0, sHealthBoxTextColor, 0, text); - u8 text[20] = __("{COLOR 01}{HIGHLIGHT 02}"); - battler = gSprites[healthboxSpriteId].sBattlerId; - if (GetBattlerCoordsIndex(battler) == TRUE || GetBattlerSide(battler) == B_SIDE_OPPONENT) - { - if (maxOrCurrent != HP_CURRENT) - UpdateHpTextInHealthboxInDoubles(healthboxSpriteId, maxOrCurrent, currHp, maxHp); - else - UpdateHpTextInHealthboxInDoubles(healthboxSpriteId, maxOrCurrent, currHp, maxHp); - } - else - { - // Only in the Japanese release can HP be displayed as text outside of double battles - u32 var; - u8 i; - - if (GetBattlerSide(gSprites[healthboxSpriteId].sBattlerId) == B_SIDE_PLAYER) - { - if (maxOrCurrent == HP_CURRENT) - var = 29; - else - var = 89; - } - else - { - if (maxOrCurrent == HP_CURRENT) - var = 20; - else - var = 48; - } - - if (maxOrCurrent != HP_CURRENT) - ConvertIntToDecimalStringN(text + 6, maxHp, STR_CONV_MODE_RIGHT_ALIGN, 3); - else - ConvertIntToDecimalStringN(text + 6, currHp, STR_CONV_MODE_RIGHT_ALIGN, 3); - RenderTextHandleBold(gMonSpritesGfxPtr->barFontGfx, 0, text); - - for (i = 0; i < 3; i++) - { - CpuCopy32(&gMonSpritesGfxPtr->barFontGfx[i * 64 + 32], - (void *)((OBJ_VRAM0) + TILE_SIZE_4BPP * (gSprites[healthboxSpriteId].oam.tileNum + var + i)), - 1 * TILE_SIZE_4BPP); - } - } - } + gSprites[spriteId].data[1] = savedValue1; + gSprites[spriteId2].data[1] = savedValue2; } -static const u8 sText_Slash[] = _("/"); - -static void UpdateHpTextInHealthboxInDoubles(u8 healthboxSpriteId, u32 maxOrCurrent, s16 currHp, s16 maxHp) +// Note: this is only possible to trigger via debug, it was an unused GF function. +static void UpdateOpponentHpTextDoubles(u32 healthboxSpriteId, u32 barSpriteId, s16 value, u8 maxOrCurrent) { - u8 battlerId; - u8 text[20] = __("{COLOR 01}{HIGHLIGHT 00}"); - battlerId = gSprites[healthboxSpriteId].sBattlerId; + u8 text[32], *txtPtr; + u32 i, var; + enum BattlerId battler = gSprites[healthboxSpriteId].hMain_Battler; - if (gBattleSpritesDataPtr->battlerData[battlerId].hpNumbersNoBars) + if (gBattleSpritesDataPtr->battlerData[battler].hpNumbersNoBars) // don't print text if only bars are visible { - u8 var = 4; - u8 healthBarSpriteId; - u8 *txtPtr; - u8 i; - + memcpy(text, sEmptyWhiteText_TransparentHighlight, sizeof(sEmptyWhiteText_TransparentHighlight)); if (maxOrCurrent == HP_CURRENT) var = 0; - - healthBarSpriteId = gSprites[healthboxSpriteId].sHealthBarSpriteId; - if (maxOrCurrent == HP_CURRENT) - txtPtr = ConvertIntToDecimalStringN(text + 6, currHp, STR_CONV_MODE_RIGHT_ALIGN, 3); else - txtPtr = ConvertIntToDecimalStringN(text + 6, maxHp, STR_CONV_MODE_RIGHT_ALIGN, 3); + var = 4; - if (maxOrCurrent == HP_CURRENT) - StringCopy(txtPtr, sText_Slash); - - RenderTextHandleBold(gMonSpritesGfxPtr->barFontGfx, 0, text); + txtPtr = ConvertIntToDecimalStringN(text + 9, value, STR_CONV_MODE_RIGHT_ALIGN, 3); + if (!maxOrCurrent) + StringCopy(txtPtr, gText_Slash); + RenderTextHandleBold(gMonSpritesGfxPtr->barFontGfx, FONT_BOLD, text); for (i = var; i < var + 3; i++) { if (i < 3) { CpuCopy32(&gMonSpritesGfxPtr->barFontGfx[((i - var) * 64) + 32], - (void *)((OBJ_VRAM0) + (1 + gSprites[healthBarSpriteId].oam.tileNum + i) * TILE_SIZE_4BPP), - 1 * TILE_SIZE_4BPP); + (void *)((OBJ_VRAM0) + 32 * (1 + gSprites[barSpriteId].oam.tileNum + i)), + 0x20); } else { CpuCopy32(&gMonSpritesGfxPtr->barFontGfx[((i - var) * 64) + 32], - (void *)((OBJ_VRAM0 + 0x20) + (i + gSprites[healthBarSpriteId].oam.tileNum) * TILE_SIZE_4BPP), - 1 * TILE_SIZE_4BPP); + (void *)((OBJ_VRAM0 + 0x20) + 32 * (i + gSprites[barSpriteId].oam.tileNum)), + 0x20); } } if (maxOrCurrent == HP_CURRENT) { CpuCopy32(&gMonSpritesGfxPtr->barFontGfx[224], - (void *)((OBJ_VRAM0) + ((gSprites[healthBarSpriteId].oam.tileNum + 4) * TILE_SIZE_4BPP)), - 1 * TILE_SIZE_4BPP); - CpuFill32(0, - (void *)((OBJ_VRAM0) + (gSprites[healthBarSpriteId].oam.tileNum * TILE_SIZE_4BPP)), - 1 * TILE_SIZE_4BPP); + (void *)((OBJ_VRAM0) + ((gSprites[barSpriteId].oam.tileNum + 4) * TILE_SIZE_4BPP)), + 0x20); + CpuFill32(0, (void *)((OBJ_VRAM0) + (gSprites[barSpriteId].oam.tileNum * TILE_SIZE_4BPP)), 0x20); } + } +} + +// Same with this one. +static void UpdateOpponentHpTextSingles(u32 healthboxSpriteId, s16 value, u32 maxOrCurrent) +{ + u8 text[32]; + u32 var, i; + enum BattlerId battler = gSprites[healthboxSpriteId].hMain_Battler; + + memcpy(text, sEmptyWhiteText_GrayHighlight, sizeof(sEmptyWhiteText_GrayHighlight)); + if (gBattleSpritesDataPtr->battlerData[battler].hpNumbersNoBars) // don't print text if only bars are visible + { + if (maxOrCurrent == HP_CURRENT) + var = 21; else + var = 49; + + ConvertIntToDecimalStringN(text + 6, value, STR_CONV_MODE_LEADING_ZEROS, 3); + RenderTextHandleBold(gMonSpritesGfxPtr->barFontGfx, FONT_BOLD, text); + + for (i = 0; i < 3; i++) { - if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) - { - CpuCopy32(GetBattleInterfaceGfxPtr(B_INTERFACE_GFX_BOTTOM_RIGHT_CORNER_HP_AS_TEXT), - (void *)(OBJ_VRAM0) + ((gSprites[healthboxSpriteId].oam.tileNum + 52) * TILE_SIZE_4BPP), - 1 * TILE_SIZE_4BPP); - } + CpuCopy32(&gMonSpritesGfxPtr->barFontGfx[i * 64 + 32], + (void *)((OBJ_VRAM0) + TILE_SIZE_4BPP * (gSprites[healthboxSpriteId].oam.tileNum + var + i)), + 0x20); } } } +void UpdateHpTextInHealthbox(u32 healthboxSpriteId, u32 maxOrCurrent, s16 currHp, s16 maxHp) +{ + enum BattlerId battler = gSprites[healthboxSpriteId].hMain_Battler; + switch (GetBattlerCoordsIndex(battler)) + { + default: + { + UpdateHpTextInHealthboxInDoubles(healthboxSpriteId, maxOrCurrent, currHp, maxHp); + break; + } + case BATTLE_COORDS_SINGLES: + { + if (IsOnPlayerSide(battler)) // Player + { + PrintHpOnHealthbox(healthboxSpriteId, currHp, maxHp, HEALTHBOX_BG_INDEX, 16); + } + else // Opponent + { + UpdateOpponentHpTextSingles(healthboxSpriteId, currHp, HP_CURRENT); + UpdateOpponentHpTextSingles(healthboxSpriteId, maxHp, HP_MAX); + } + break; + } + } +} + +static void UpdateHpTextInHealthboxInDoubles(u32 healthboxSpriteId, u32 maxOrCurrent, s16 currHp, s16 maxHp) +{ + u32 barSpriteId = gSprites[healthboxSpriteId].data[5]; + enum BattlerId battler = gSprites[healthboxSpriteId].hMain_Battler; + + if (IsOnPlayerSide(battler)) + { + if (gBattleSpritesDataPtr->battlerData[gSprites[healthboxSpriteId].data[6]].hpNumbersNoBars) // don't print text if only bars are visible + { + PrintHpOnHealthbox(healthboxSpriteId, currHp, maxHp, HEALTHBOX_BG_INDEX, 8); + // Clears the end of the healthbar gfx. + CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_FRAME_END), + (void *)(OBJ_VRAM0 + 0x680) + (gSprites[healthboxSpriteId].oam.tileNum * TILE_SIZE_4BPP), + 0x20); + // Erases HP bar leftover. + FillHealthboxObject((void *)(OBJ_VRAM0) + (gSprites[barSpriteId].oam.tileNum * TILE_SIZE_4BPP), 0, 2); + } + } + else // Opponent + { + UpdateOpponentHpTextDoubles(healthboxSpriteId, barSpriteId, maxHp, HP_MAX); + UpdateOpponentHpTextDoubles(healthboxSpriteId, barSpriteId, currHp, HP_CURRENT); + } +} + // Prints mon's nature, catch and flee rate. Probably used to test pokeblock-related features. static void PrintSafariMonInfo(u8 healthboxSpriteId, struct Pokemon *mon) { - u8 text[20] = __("{COLOR 01}{HIGHLIGHT 02}"); + u8 text[23]; s32 j, spriteTileNum; u8 *barFontGfx; u8 i, var, nature, healthBarSpriteId; - barFontGfx = &gMonSpritesGfxPtr->barFontGfx[0x520 + (GetBattlerPosition(gSprites[healthboxSpriteId].sBattlerId) * 384)]; + memcpy(text, sEmptyWhiteText_GrayHighlight, sizeof(sEmptyWhiteText_GrayHighlight)); + barFontGfx = &gMonSpritesGfxPtr->barFontGfx[0x520 + (GetBattlerPosition(gSprites[healthboxSpriteId].hMain_Battler) * 384)]; var = 5; nature = GetNature(mon); - StringCopy(text + 6, gNaturesInfo[nature].name); - RenderTextHandleBold(barFontGfx, 0, text); + StringCopy(&text[9], gNaturesInfo[nature].name); + RenderTextHandleBold(barFontGfx, FONT_BOLD, text); - for (j = 6, i = 0; i < var; i++, j++) + for (j = 9, i = 0; i < var; i++, j++) { u8 elementId; if ((text[j] >= 55 && text[j] <= 74) || (text[j] >= 135 && text[j] <= 154)) - elementId = B_INTERFACE_GFX_SAFARI_HEALTHBOX_1; + elementId = 44; else if ((text[j] >= 75 && text[j] <= 79) || (text[j] >= 155 && text[j] <= 159)) - elementId = B_INTERFACE_GFX_SAFARI_HEALTHBOX_2; + elementId = 45; else - elementId = B_INTERFACE_GFX_SAFARI_HEALTHBOX_0; + elementId = 43; - CpuCopy32(GetBattleInterfaceGfxPtr(elementId), barFontGfx + (i * 64), 0x20); + CpuCopy32(GetHealthboxElementGfxPtr(elementId), barFontGfx + (i * 64), 0x20); } for (j = 1; j < var + 1; j++) @@ -1048,12 +1096,13 @@ static void PrintSafariMonInfo(u8 healthboxSpriteId, struct Pokemon *mon) barFontGfx += 0x20; } - healthBarSpriteId = gSprites[healthboxSpriteId].sHealthBarSpriteId; - ConvertIntToDecimalStringN(text + 6, gBattleStruct->safariCatchFactor, STR_CONV_MODE_RIGHT_ALIGN, 2); - ConvertIntToDecimalStringN(text + 9, gBattleStruct->safariEscapeFactor, STR_CONV_MODE_RIGHT_ALIGN, 2); - text[5] = CHAR_SPACE; - text[8] = CHAR_SLASH; - RenderTextHandleBold(gMonSpritesGfxPtr->barFontGfx, 0, text); + healthBarSpriteId = gSprites[healthboxSpriteId].hMain_HealthBarSpriteId; + ConvertIntToDecimalStringN(&text[9], gBattleStruct->safariCatchFactor, STR_CONV_MODE_RIGHT_ALIGN, 2); + ConvertIntToDecimalStringN(&text[12], gBattleStruct->safariEscapeFactor, STR_CONV_MODE_RIGHT_ALIGN, 2); + text[5] = TEXT_COLOR_TRANSPARENT; + text[8] = TEXT_COLOR_TRANSPARENT; + text[11] = CHAR_SLASH; + RenderTextHandleBold(gMonSpritesGfxPtr->barFontGfx, FONT_BOLD, text); j = healthBarSpriteId; // Needed to match for some reason. for (j = 0; j < 5; j++) @@ -1075,43 +1124,42 @@ static void PrintSafariMonInfo(u8 healthboxSpriteId, struct Pokemon *mon) void SwapHpBarsWithHpText(void) { - s32 i; - u8 healthBarSpriteId; + u32 healthBarSpriteId; - for (i = 0; i < gBattlersCount; i++) + for (enum BattlerId i = 0; i < gBattlersCount; i++) { + struct Pokemon *mon = GetBattlerMon(i); if (gSprites[gHealthboxSpriteIds[i]].callback == SpriteCallbackDummy - && GetBattlerSide(i) != B_SIDE_OPPONENT - && (GetBattlerCoordsIndex(i) || GetBattlerSide(i) != B_SIDE_PLAYER)) + && IsOnPlayerSide(i) + && (GetBattlerCoordsIndex(i) != BATTLE_COORDS_SINGLES || !IsOnPlayerSide(i))) { + s32 currHp = GetMonData(mon, MON_DATA_HP); + s32 maxHp = GetMonData(mon, MON_DATA_MAX_HP); bool8 noBars; gBattleSpritesDataPtr->battlerData[i].hpNumbersNoBars ^= 1; noBars = gBattleSpritesDataPtr->battlerData[i].hpNumbersNoBars; - if (GetBattlerSide(i) == B_SIDE_PLAYER) + if (IsOnPlayerSide(i)) { - if (!GetBattlerCoordsIndex(i)) + if (GetBattlerCoordsIndex(i) == BATTLE_COORDS_SINGLES) continue; if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) continue; if (noBars == TRUE) // bars to text { - s16 currHp = GetMonData(&gPlayerParty[gBattlerPartyIndexes[i]], MON_DATA_HP); - s16 maxHp = GetMonData(&gPlayerParty[gBattlerPartyIndexes[i]], MON_DATA_MAX_HP); - healthBarSpriteId = gSprites[gHealthboxSpriteIds[i]].sHealthBarSpriteId; + healthBarSpriteId = gSprites[gHealthboxSpriteIds[i]].hMain_HealthBarSpriteId; - CpuFill32(0, (void *)(OBJ_VRAM0 + gSprites[healthBarSpriteId].oam.tileNum * TILE_SIZE_4BPP), 8 * TILE_SIZE_4BPP); - UpdateHpTextInHealthboxInDoubles(gHealthboxSpriteIds[i], HP_CURRENT, currHp, maxHp); - UpdateHpTextInHealthboxInDoubles(gHealthboxSpriteIds[i], HP_MAX, currHp, maxHp); + CpuFill32(0, (void *)(OBJ_VRAM0 + gSprites[healthBarSpriteId].oam.tileNum * TILE_SIZE_4BPP), 0x100); + UpdateHpTextInHealthboxInDoubles(gHealthboxSpriteIds[i], HP_BOTH, currHp, maxHp); } else // text to bars { + FillSpriteRectColor(gHealthboxSpriteIds[i], 32, 16, 32, 9, HEALTHBOX_BG_INDEX); + FillSpriteRectColor(gSprites[gHealthboxSpriteIds[i]].oam.affineParam, 0, 16, 32, 9, HEALTHBOX_BG_INDEX); UpdateStatusIconInHealthbox(gHealthboxSpriteIds[i]); - UpdateHealthboxAttribute(gHealthboxSpriteIds[i], &gPlayerParty[gBattlerPartyIndexes[i]], HEALTHBOX_HEALTH_BAR); - CpuCopy32(GetBattleInterfaceGfxPtr(B_INTERFACE_GFX_BOTTOM_RIGHT_CORNER_HP_AS_BAR), - (void *)(OBJ_VRAM0 + 0x680 + gSprites[gHealthboxSpriteIds[i]].oam.tileNum * TILE_SIZE_4BPP), - 1 * TILE_SIZE_4BPP); + UpdateHealthboxAttribute(gHealthboxSpriteIds[i], mon, HEALTHBOX_HEALTH_BAR); + CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_FRAME_END_BAR), (void *)(OBJ_VRAM0 + 0x680 + gSprites[gHealthboxSpriteIds[i]].oam.tileNum * TILE_SIZE_4BPP), 32); } } else @@ -1121,50 +1169,39 @@ void SwapHpBarsWithHpText(void) if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) { // Most likely a debug function. - PrintSafariMonInfo(gHealthboxSpriteIds[i], &gEnemyParty[gBattlerPartyIndexes[i]]); + PrintSafariMonInfo(gHealthboxSpriteIds[i], mon); } else { - s16 currHp = GetMonData(&gEnemyParty[gBattlerPartyIndexes[i]], MON_DATA_HP); - s16 maxHp = GetMonData(&gEnemyParty[gBattlerPartyIndexes[i]], MON_DATA_MAX_HP); - healthBarSpriteId = gSprites[gHealthboxSpriteIds[i]].sHealthBarSpriteId; + healthBarSpriteId = gSprites[gHealthboxSpriteIds[i]].hMain_HealthBarSpriteId; - CpuFill32(0, (void *)(OBJ_VRAM0 + gSprites[healthBarSpriteId].oam.tileNum * 32), 8 * TILE_SIZE_4BPP); - UpdateHpTextInHealthboxInDoubles(gHealthboxSpriteIds[i], HP_CURRENT, currHp, maxHp); - UpdateHpTextInHealthboxInDoubles(gHealthboxSpriteIds[i], HP_MAX, currHp, maxHp); + CpuFill32(0, (void *)(OBJ_VRAM0 + gSprites[healthBarSpriteId].oam.tileNum * 32), 0x100); + UpdateHpTextInHealthboxInDoubles(gHealthboxSpriteIds[i], HP_BOTH, currHp, maxHp); } } else // text to bars { UpdateStatusIconInHealthbox(gHealthboxSpriteIds[i]); - UpdateHealthboxAttribute(gHealthboxSpriteIds[i], &gEnemyParty[gBattlerPartyIndexes[i]], HEALTHBOX_HEALTH_BAR); + UpdateHealthboxAttribute(gHealthboxSpriteIds[i], mon, HEALTHBOX_HEALTH_BAR); if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) - UpdateHealthboxAttribute(gHealthboxSpriteIds[i], &gEnemyParty[gBattlerPartyIndexes[i]], HEALTHBOX_NICK); + UpdateHealthboxAttribute(gHealthboxSpriteIds[i], mon, HEALTHBOX_NICK); } } - gSprites[gHealthboxSpriteIds[i]].data[7] ^= 1; + gSprites[gHealthboxSpriteIds[i]].hMain_Data7 ^= 1; } } } +#undef tBattler +#undef tType +#undef tPosX +#undef tLevelXDelta #define tBattler data[0] #define tSummaryBarSpriteId data[1] #define tBallIconSpriteId(n) data[3 + n] #define tIsBattleStart data[10] -#define tTimer data[11] -#define tBlendWeight data[15] - -// sprite data for party summary bar -#define sEnterSpeed data[0] -#define sExitSpeed data[1] - -// sprite data for party summary ball icon -#define sSummaryBarSpriteId data[0] -#define sTimer data[1] -#define sIsOpponent data[2] -#define sSpeed data[3] -#define sIsEmptyBall data[7] +#define tBlend data[15] u8 CreatePartyStatusSummarySprites(enum BattlerId battler, struct HpAndStatus *partyInfo, bool8 skipPlayer, bool8 isBattleStart) { @@ -1213,7 +1250,7 @@ u8 CreatePartyStatusSummarySprites(enum BattlerId battler, struct HpAndStatus *p summaryBarSpriteId = CreateSprite(&sStatusSummaryBarSpriteTemplates[isOpponent], bar_X, bar_Y, 10); SetSubspriteTables(&gSprites[summaryBarSpriteId], sStatusSummaryBar_SubspriteTable_Enter); gSprites[summaryBarSpriteId].x2 = bar_pos2_X; - gSprites[summaryBarSpriteId].sEnterSpeed = bar_data0; + gSprites[summaryBarSpriteId].data[0] = bar_data0; if (isOpponent) { @@ -1230,7 +1267,7 @@ u8 CreatePartyStatusSummarySprites(enum BattlerId battler, struct HpAndStatus *p ballIconSpritesIds[i] = CreateSpriteAtEnd(&sStatusSummaryBallsSpriteTemplates[isOpponent], bar_X, bar_Y - 4, 9); if (!isBattleStart) - gSprites[ballIconSpritesIds[i]].callback = SpriteCB_PartySummaryBall_OnSwitchout; + gSprites[ballIconSpritesIds[i]].callback = SpriteCB_StatusSummaryBalls_OnSwitchout; if (!isOpponent) { @@ -1238,22 +1275,22 @@ u8 CreatePartyStatusSummarySprites(enum BattlerId battler, struct HpAndStatus *p gSprites[ballIconSpritesIds[i]].y2 = 0; } - gSprites[ballIconSpritesIds[i]].sSummaryBarSpriteId = summaryBarSpriteId; + gSprites[ballIconSpritesIds[i]].data[0] = summaryBarSpriteId; if (!isOpponent) { gSprites[ballIconSpritesIds[i]].x += 10 * i + 24; - gSprites[ballIconSpritesIds[i]].sTimer = i * 7 + 10; + gSprites[ballIconSpritesIds[i]].data[1] = i * 7 + 10; gSprites[ballIconSpritesIds[i]].x2 = 120; } else { gSprites[ballIconSpritesIds[i]].x -= 10 * (5 - i) + 24; - gSprites[ballIconSpritesIds[i]].sTimer = (6 - i) * 7 + 10; + gSprites[ballIconSpritesIds[i]].data[1] = (6 - i) * 7 + 10; gSprites[ballIconSpritesIds[i]].x2 = -120; } - gSprites[ballIconSpritesIds[i]].sIsOpponent = isOpponent; + gSprites[ballIconSpritesIds[i]].data[2] = isOpponent; } if (IsOnPlayerSide(battler)) @@ -1266,14 +1303,14 @@ u8 CreatePartyStatusSummarySprites(enum BattlerId battler, struct HpAndStatus *p { // empty slot or an egg gSprites[ballIconSpritesIds[i]].oam.tileNum += 1; - gSprites[ballIconSpritesIds[i]].sIsEmptyBall = TRUE; + gSprites[ballIconSpritesIds[i]].data[7] = 1; } else if (partyInfo[i].hp == 0) { // fainted mon gSprites[ballIconSpritesIds[i]].oam.tileNum += 3; } - else if (partyInfo[i].status != STATUS1_NONE) + else if (partyInfo[i].status != 0) { // mon with major status gSprites[ballIconSpritesIds[i]].oam.tileNum += 2; @@ -1288,7 +1325,7 @@ u8 CreatePartyStatusSummarySprites(enum BattlerId battler, struct HpAndStatus *p { // empty slot or an egg gSprites[ballIconSpritesIds[var]].oam.tileNum += 1; - gSprites[ballIconSpritesIds[var]].sIsEmptyBall = TRUE; + gSprites[ballIconSpritesIds[var]].data[7] = 1; var--; continue; } @@ -1302,7 +1339,7 @@ u8 CreatePartyStatusSummarySprites(enum BattlerId battler, struct HpAndStatus *p // fainted arena mon gSprites[ballIconSpritesIds[i]].oam.tileNum += 3; } - else if (partyInfo[j].status != STATUS1_NONE) + else if (partyInfo[j].status != 0) { // mon with primary status gSprites[ballIconSpritesIds[i]].oam.tileNum += 2; @@ -1321,14 +1358,14 @@ u8 CreatePartyStatusSummarySprites(enum BattlerId battler, struct HpAndStatus *p { // empty slot or an egg gSprites[ballIconSpritesIds[var]].oam.tileNum += 1; - gSprites[ballIconSpritesIds[var]].sIsEmptyBall = TRUE; + gSprites[ballIconSpritesIds[var]].data[7] = 1; } else if (partyInfo[i].hp == 0) { // fainted mon gSprites[ballIconSpritesIds[var]].oam.tileNum += 3; } - else if (partyInfo[i].status != STATUS1_NONE) + else if (partyInfo[i].status != 0) { // mon with primary status gSprites[ballIconSpritesIds[var]].oam.tileNum += 2; @@ -1344,7 +1381,7 @@ u8 CreatePartyStatusSummarySprites(enum BattlerId battler, struct HpAndStatus *p { // empty slot or an egg gSprites[ballIconSpritesIds[i]].oam.tileNum += 1; - gSprites[ballIconSpritesIds[i]].sIsEmptyBall = TRUE; + gSprites[ballIconSpritesIds[i]].data[7] = 1; i++; continue; } @@ -1358,7 +1395,7 @@ u8 CreatePartyStatusSummarySprites(enum BattlerId battler, struct HpAndStatus *p // fainted arena mon gSprites[ballIconSpritesIds[PARTY_SIZE - 1 - var]].oam.tileNum += 3; } - else if (partyInfo[j].status != STATUS1_NONE) + else if (partyInfo[j].status != 0) { // mon with primary status gSprites[ballIconSpritesIds[PARTY_SIZE - 1 - var]].oam.tileNum += 2; @@ -1386,17 +1423,18 @@ u8 CreatePartyStatusSummarySprites(enum BattlerId battler, struct HpAndStatus *p return taskId; } +// Slide the party summary tray back offscreen void Task_HidePartyStatusSummary(u8 taskId) { u8 ballIconSpriteIds[PARTY_SIZE]; bool8 isBattleStart; u8 summaryBarSpriteId; - u8 battlerId; + enum BattlerId battler; s32 i; isBattleStart = gTasks[taskId].tIsBattleStart; summaryBarSpriteId = gTasks[taskId].tSummaryBarSpriteId; - battlerId = gTasks[taskId].tBattler; + battler = gTasks[taskId].tBattler; for (i = 0; i < PARTY_SIZE; i++) ballIconSpriteIds[i] = gTasks[taskId].tBallIconSpriteId(i); @@ -1404,7 +1442,7 @@ void Task_HidePartyStatusSummary(u8 taskId) SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND); SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); - gTasks[taskId].tBlendWeight = 16; + gTasks[taskId].tBlend = 16; for (i = 0; i < PARTY_SIZE; i++) gSprites[ballIconSpriteIds[i]].oam.objMode = ST_OAM_OBJ_BLEND; @@ -1415,42 +1453,43 @@ void Task_HidePartyStatusSummary(u8 taskId) { for (i = 0; i < PARTY_SIZE; i++) { - if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(battler)) { - gSprites[ballIconSpriteIds[5 - i]].sTimer = 7 * i; - gSprites[ballIconSpriteIds[5 - i]].sSpeed = 0; - gSprites[ballIconSpriteIds[5 - i]].data[4] = 0; - gSprites[ballIconSpriteIds[5 - i]].callback = SpriteCB_PartySummaryBall_Exit; + gSprites[ballIconSpriteIds[PARTY_SIZE - 1 - i]].data[1] = 7 * i; + gSprites[ballIconSpriteIds[PARTY_SIZE - 1 - i]].data[3] = 0; + gSprites[ballIconSpriteIds[PARTY_SIZE - 1 - i]].data[4] = 0; + gSprites[ballIconSpriteIds[PARTY_SIZE - 1 - i]].callback = SpriteCB_StatusSummaryBalls_Exit; } else { - gSprites[ballIconSpriteIds[i]].sTimer = 7 * i; - gSprites[ballIconSpriteIds[i]].sSpeed = 0; + gSprites[ballIconSpriteIds[i]].data[1] = 7 * i; + gSprites[ballIconSpriteIds[i]].data[3] = 0; gSprites[ballIconSpriteIds[i]].data[4] = 0; - gSprites[ballIconSpriteIds[i]].callback = SpriteCB_PartySummaryBall_Exit; + gSprites[ballIconSpriteIds[i]].callback = SpriteCB_StatusSummaryBalls_Exit; } } - gSprites[summaryBarSpriteId].sEnterSpeed /= 2; - gSprites[summaryBarSpriteId].sExitSpeed = 0; - gSprites[summaryBarSpriteId].callback = SpriteCB_PartySummaryBar_Exit; + gSprites[summaryBarSpriteId].data[0] /= 2; + gSprites[summaryBarSpriteId].data[1] = 0; + gSprites[summaryBarSpriteId].callback = SpriteCB_StatusSummaryBar_Exit; SetSubspriteTables(&gSprites[summaryBarSpriteId], sStatusSummaryBar_SubspriteTable_Exit); gTasks[taskId].func = Task_HidePartyStatusSummary_BattleStart_1; } else + { gTasks[taskId].func = Task_HidePartyStatusSummary_DuringBattle; - + } } static void Task_HidePartyStatusSummary_BattleStart_1(u8 taskId) { - if ((gTasks[taskId].tTimer++ % 2) == 0) + if ((gTasks[taskId].data[11]++ % 2) == 0) { - if (--gTasks[taskId].tBlendWeight < 0) + if (--gTasks[taskId].tBlend < 0) return; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].tBlendWeight, 16 - gTasks[taskId].tBlendWeight)); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].tBlend, 16 - gTasks[taskId].tBlend)); } - if (gTasks[taskId].tBlendWeight == 0) + if (gTasks[taskId].tBlend == 0) gTasks[taskId].func = Task_HidePartyStatusSummary_BattleStart_2; } @@ -1459,21 +1498,34 @@ static void Task_HidePartyStatusSummary_BattleStart_2(u8 taskId) u8 ballIconSpriteIds[PARTY_SIZE]; s32 i; - if (--gTasks[taskId].tBlendWeight == -1) + enum BattlerId battler = gTasks[taskId].tBattler; + if (--gTasks[taskId].tBlend == -1) { u8 summaryBarSpriteId = gTasks[taskId].tSummaryBarSpriteId; for (i = 0; i < PARTY_SIZE; i++) ballIconSpriteIds[i] = gTasks[taskId].tBallIconSpriteId(i); - DestroySpriteAndFreeResources(&gSprites[summaryBarSpriteId]); - DestroySpriteAndFreeResources(&gSprites[ballIconSpriteIds[0]]); + gBattleSpritesDataPtr->animationData->field_9_x1C--; + if (gBattleSpritesDataPtr->animationData->field_9_x1C == 0) + { + DestroySpriteAndFreeResources(&gSprites[summaryBarSpriteId]); + DestroySpriteAndFreeResources(&gSprites[ballIconSpriteIds[0]]); + } + else + { + FreeSpriteOamMatrix(&gSprites[summaryBarSpriteId]); + DestroySprite(&gSprites[summaryBarSpriteId]); + FreeSpriteOamMatrix(&gSprites[ballIconSpriteIds[0]]); + DestroySprite(&gSprites[ballIconSpriteIds[0]]); + } for (i = 1; i < PARTY_SIZE; i++) DestroySprite(&gSprites[ballIconSpriteIds[i]]); } - else if (gTasks[taskId].tBlendWeight == -3) + else if (gTasks[taskId].tBlend == -3) { + gBattleSpritesDataPtr->healthBoxesData[battler].partyStatusSummaryShown = 0; SetGpuReg(REG_OFFSET_BLDCNT, 0); SetGpuReg(REG_OFFSET_BLDALPHA, 0); DestroyTask(taskId); @@ -1484,10 +1536,13 @@ static void Task_HidePartyStatusSummary_DuringBattle(u8 taskId) { u8 ballIconSpriteIds[PARTY_SIZE]; s32 i; + enum BattlerId battler = gTasks[taskId].tBattler; - if (--gTasks[taskId].tBlendWeight >= 0) - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].tBlendWeight, 16 - gTasks[taskId].tBlendWeight)); - else if (gTasks[taskId].tBlendWeight == -1) + if (--gTasks[taskId].tBlend >= 0) + { + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].tBlend, 16 - gTasks[taskId].tBlend)); + } + else if (gTasks[taskId].tBlend == -1) { u8 summaryBarSpriteId = gTasks[taskId].tSummaryBarSpriteId; @@ -1500,8 +1555,9 @@ static void Task_HidePartyStatusSummary_DuringBattle(u8 taskId) for (i = 1; i < PARTY_SIZE; i++) DestroySprite(&gSprites[ballIconSpriteIds[i]]); } - else if (gTasks[taskId].tBlendWeight == -3) + else if (gTasks[taskId].tBlend == -3) { + gBattleSpritesDataPtr->healthBoxesData[battler].partyStatusSummaryShown = 0; SetGpuReg(REG_OFFSET_BLDCNT, 0); SetGpuReg(REG_OFFSET_BLDALPHA, 0); DestroyTask(taskId); @@ -1512,57 +1568,61 @@ static void Task_HidePartyStatusSummary_DuringBattle(u8 taskId) #undef tSummaryBarSpriteId #undef tBallIconSpriteId #undef tIsBattleStart -#undef tBlendWeight +#undef tBlend -static void SpriteCB_PartySummaryBar(struct Sprite *sprite) +static void SpriteCB_StatusSummaryBar_Enter(struct Sprite *sprite) { if (sprite->x2 != 0) - sprite->x2 += sprite->sEnterSpeed; + sprite->x2 += sprite->data[0]; } -static void SpriteCB_PartySummaryBar_Exit(struct Sprite *sprite) +static void SpriteCB_StatusSummaryBar_Exit(struct Sprite *sprite) { - sprite->sExitSpeed += 32; - if (sprite->sEnterSpeed > 0) - sprite->x2 += sprite->sExitSpeed >> 4; + sprite->data[1] += 32; + if (sprite->data[0] > 0) + sprite->x2 += sprite->data[1] >> 4; else - sprite->x2 -= sprite->sExitSpeed >> 4; - sprite->sExitSpeed &= 0xF; + sprite->x2 -= sprite->data[1] >> 4; + sprite->data[1] &= 0xF; } -static void SpriteCB_PartySummaryBall_OnBattleStart(struct Sprite *sprite) +static void SpriteCB_StatusSummaryBalls_Enter(struct Sprite *sprite) { - bool8 isOpponent; - u16 speed; + u8 var1; + u16 var2; + s8 pan; - if (sprite->sTimer > 0) + if (sprite->data[1] > 0) { - sprite->sTimer--; + sprite->data[1]--; return; } - isOpponent = sprite->sIsOpponent; - speed = sprite->sSpeed; - speed += 56; - sprite->sSpeed = speed & 0xFFF0; + var1 = sprite->data[2]; + var2 = sprite->data[3]; + var2 += 56; + sprite->data[3] = var2 & 0xFFF0; - if (isOpponent != FALSE) + if (var1 != 0) { - sprite->x2 += speed / 16; + sprite->x2 += var2 >> 4; if (sprite->x2 > 0) sprite->x2 = 0; } else { - sprite->x2 -= speed / 16; + sprite->x2 -= var2 >> 4; if (sprite->x2 < 0) sprite->x2 = 0; } if (sprite->x2 == 0) { - s8 pan = isOpponent ? SOUND_PAN_ATTACKER : SOUND_PAN_TARGET; - if (sprite->sIsEmptyBall != FALSE) + pan = SOUND_PAN_TARGET; + if (var1 != 0) + pan = SOUND_PAN_ATTACKER; + + if (sprite->data[7] != 0) PlaySE2WithPanning(SE_BALL_TRAY_EXIT, pan); else PlaySE1WithPanning(SE_BALL_TRAY_BALL, pan); @@ -1571,321 +1631,283 @@ static void SpriteCB_PartySummaryBall_OnBattleStart(struct Sprite *sprite) } } -static void SpriteCB_PartySummaryBall_Exit(struct Sprite *sprite) +static void SpriteCB_StatusSummaryBalls_Exit(struct Sprite *sprite) { - bool8 isOpponent; - u16 speed; + u8 var1; + u16 var2; - if (sprite->sTimer > 0) + if (sprite->data[1] > 0) { - sprite->sTimer--; + sprite->data[1]--; return; } - isOpponent = sprite->sIsOpponent; - speed = sprite->sSpeed; - speed += 56; - sprite->sSpeed = speed & 0xFFF0; - if (isOpponent != FALSE) - sprite->x2 += speed / 16; + var1 = sprite->data[2]; + var2 = sprite->data[3]; + var2 += 56; + sprite->data[3] = var2 & 0xFFF0; + if (var1 != 0) + sprite->x2 += var2 >> 4; else - sprite->x2 -= speed / 16; - - if (sprite->x2 + sprite->x > DISPLAY_WIDTH + 8 || sprite->x2 + sprite->x < -8) + sprite->x2 -= var2 >> 4; + if (sprite->x2 + sprite->x > 248 + || sprite->x2 + sprite->x < -8) { sprite->invisible = TRUE; sprite->callback = SpriteCallbackDummy; } } -static void SpriteCB_PartySummaryBall_OnSwitchout(struct Sprite *sprite) +static void SpriteCB_StatusSummaryBalls_OnSwitchout(struct Sprite *sprite) { - u8 summaryBarSpriteId = sprite->sSummaryBarSpriteId; + u8 barSpriteId = sprite->data[0]; - sprite->x2 = gSprites[summaryBarSpriteId].x2; - sprite->y2 = gSprites[summaryBarSpriteId].y2; + sprite->x2 = gSprites[barSpriteId].x2; + sprite->y2 = gSprites[barSpriteId].y2; } - -#undef sSummaryBarSpriteId -#undef sTimer -#undef sIsOpponent -#undef sSpeed -#undef sIsEmptyBall - -#undef sEnterSpeed -#undef sExitSpeed - -static const u8 sText_HealthboxNickname[] = _("{HIGHLIGHT 02}"); - void UpdateNickInHealthbox(u8 healthboxSpriteId, struct Pokemon *mon) { + u32 healthboxSpriteId2 = gSprites[healthboxSpriteId].oam.affineParam; u8 nickname[POKEMON_NAME_LENGTH + 1]; - u8 *ptr; - u32 windowId, spriteTileNum; - u8 *windowTileData; - u16 species; + void *ptr; + u32 species; u8 gender; + struct Pokemon *illusionMon = GetIllusionMonPtr(gSprites[healthboxSpriteId].hMain_Battler); + if (illusionMon != NULL) + mon = illusionMon; - ptr = StringCopy(gDisplayedStringBattle, sText_HealthboxNickname); GetMonData(mon, MON_DATA_NICKNAME, nickname); StringGet_Nickname(nickname); - ptr = StringCopy(ptr, nickname); - *ptr++ = EXT_CTRL_CODE_BEGIN; - *ptr++ = EXT_CTRL_CODE_COLOR; + ptr = StringCopy(gDisplayedStringBattle, nickname); gender = GetMonGender(mon); species = GetMonData(mon, MON_DATA_SPECIES); - if ((species == SPECIES_NIDORAN_F || species == SPECIES_NIDORAN_M) && StringCompare(nickname, gSpeciesInfo[species].speciesName) == 0) + if ((species == SPECIES_NIDORAN_F || species == SPECIES_NIDORAN_M) && StringCompare(nickname, GetSpeciesName(species)) == 0) gender = 100; - if (CheckBattleTypeGhost(mon, gSprites[healthboxSpriteId].sBattlerId)) + if (GetBattlerSide(gSprites[healthboxSpriteId].hMain_Battler) == B_SIDE_OPPONENT && IsGhostBattleWithoutScope()) gender = 100; - // AddTextPrinterAndCreateWindowOnHealthbox's arguments are the same in all 3 cases. - // It's possible they may have been different in early development phases. switch (gender) { default: - *ptr++ = TEXT_DYNAMIC_COLOR_2; - *ptr++ = EOS; - windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(gDisplayedStringBattle, 0, 3, &windowId); + StringCopy(ptr, gText_HealthboxGender_None); break; case MON_MALE: - *ptr++ = TEXT_DYNAMIC_COLOR_2; - *ptr++ = CHAR_MALE; - *ptr++ = EOS; - windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(gDisplayedStringBattle, 0, 3, &windowId); + StringCopy(ptr, gText_HealthboxGender_Male); break; case MON_FEMALE: - *ptr++ = TEXT_DYNAMIC_COLOR_1; - *ptr++ = CHAR_FEMALE; - *ptr++ = EOS; - windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(gDisplayedStringBattle, 0, 3, &windowId); + StringCopy(ptr, gText_HealthboxGender_Female); break; } - spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * TILE_SIZE_4BPP; + // Don't assume that healthbox sprites don't have data in the fields used for sprite printing + // and set up temporary values with what's needed + s16 savedValue1 = gSprites[healthboxSpriteId].data[1]; + s16 savedValue2 = gSprites[healthboxSpriteId2].data[1]; + gSprites[healthboxSpriteId].data[1] = healthboxSpriteId2; + gSprites[healthboxSpriteId2].data[1] = SPRITE_NONE; - if (GetBattlerSide(gSprites[healthboxSpriteId].sBattlerId) == B_SIDE_PLAYER) + u32 fontId = GetFontIdToFit(gDisplayedStringBattle, FONT_SMALL, 0, 55); + + if (IsOnPlayerSide(gSprites[healthboxSpriteId].data[6])) { - TextIntoHealthboxObject((void *)(OBJ_VRAM0 + 0x40 + spriteTileNum), windowTileData, 6); - ptr = (void *)(OBJ_VRAM0); - if (!GetBattlerCoordsIndex(gSprites[healthboxSpriteId].sBattlerId)) - ptr += spriteTileNum + 0x800; - else - ptr += spriteTileNum + 0x400; - - TextIntoHealthboxObject(ptr, windowTileData + 0xC0, 1); + FillSpriteRectColor(healthboxSpriteId, 16, 5, 55, 11, HEALTHBOX_BG_INDEX); + AddSpriteTextPrinterParameterized6(healthboxSpriteId, fontId, 16, 3, 0, 0, sHealthBoxTextColor, 0, gDisplayedStringBattle); } else - TextIntoHealthboxObject((void *)(OBJ_VRAM0 + 0x20 + spriteTileNum), windowTileData, 7); + { + FillSpriteRectColor(healthboxSpriteId, 8, 5, 55, 11, HEALTHBOX_BG_INDEX); + AddSpriteTextPrinterParameterized6(healthboxSpriteId, fontId, 8, 3, 0, 0, sHealthBoxTextColor, 0, gDisplayedStringBattle); + } - RemoveWindowOnHealthbox(windowId); + gSprites[healthboxSpriteId].data[1] = savedValue1; + gSprites[healthboxSpriteId2].data[1] = savedValue2; } void TryAddPokeballIconToHealthbox(u8 healthboxSpriteId, bool8 noStatus) { - u8 battlerId, healthBarSpriteId; + enum BattlerId battler; + u8 healthBarSpriteId; - if (gBattleTypeFlags & (BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_CATCH_TUTORIAL | BATTLE_TYPE_POKEDUDE)) + if (gBattleTypeFlags & BATTLE_TYPE_CATCH_TUTORIAL) return; - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) return; - battlerId = gSprites[healthboxSpriteId].sBattlerId; - if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + battler = gSprites[healthboxSpriteId].hMain_Battler; + if (IsOnPlayerSide(battler)) return; - if (CheckBattleTypeGhost(&gEnemyParty[gBattlerPartyIndexes[battlerId]], battlerId)) + if (GetBattlerSide(battler) == B_SIDE_OPPONENT && IsGhostBattleWithoutScope()) return; - if (!GetSetPokedexFlag(SpeciesToNationalPokedexNum(GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES)), FLAG_GET_CAUGHT)) + if (!GetSetPokedexFlag(SpeciesToNationalPokedexNum(GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES)), FLAG_GET_CAUGHT)) return; - healthBarSpriteId = gSprites[healthboxSpriteId].sHealthBarSpriteId; + healthBarSpriteId = gSprites[healthboxSpriteId].hMain_HealthBarSpriteId; if (noStatus) - CpuCopy32(GetBattleInterfaceGfxPtr(B_INTERFACE_GFX_BALL_CAUGHT), (void *)(OBJ_VRAM0 + (gSprites[healthBarSpriteId].oam.tileNum + 8) * TILE_SIZE_4BPP), 1 * TILE_SIZE_4BPP); + CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_STATUS_BALL_CAUGHT), (void *)(OBJ_VRAM0 + (gSprites[healthBarSpriteId].oam.tileNum + 8) * TILE_SIZE_4BPP), 32); else - CpuFill32(0, (void *)(OBJ_VRAM0 + (gSprites[healthBarSpriteId].oam.tileNum + 8) * TILE_SIZE_4BPP), 1 * TILE_SIZE_4BPP); + CpuFill32(0, (void *)(OBJ_VRAM0 + (gSprites[healthBarSpriteId].oam.tileNum + 8) * TILE_SIZE_4BPP), 32); } -enum -{ - PAL_STATUS_PSN, - PAL_STATUS_PAR, - PAL_STATUS_SLP, - PAL_STATUS_FRZ, - PAL_STATUS_BRN -}; - -static const u16 sStatusIconColors[] = { - [PAL_STATUS_PSN] = RGB(24, 12, 24), - [PAL_STATUS_PAR] = RGB(23, 23, 3), - [PAL_STATUS_SLP] = RGB(20, 20, 17), - [PAL_STATUS_FRZ] = RGB(17, 22, 28), - [PAL_STATUS_BRN] = RGB(28, 14, 10) -}; - static void UpdateStatusIconInHealthbox(u8 healthboxSpriteId) { s32 i; - u8 battlerId, healthBarSpriteId; + enum BattlerId battler; + u8 healthBarSpriteId; u32 status, pltAdder; const u8 *statusGfxPtr; s16 tileNumAdder; u8 statusPalId; - battlerId = gSprites[healthboxSpriteId].sBattlerId; - healthBarSpriteId = gSprites[healthboxSpriteId].sHealthBarSpriteId; - if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + battler = gSprites[healthboxSpriteId].hMain_Battler; + healthBarSpriteId = gSprites[healthboxSpriteId].hMain_HealthBarSpriteId; + status = GetMonData(GetBattlerMon(battler), MON_DATA_STATUS); + if (IsOnPlayerSide(battler)) { - status = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_STATUS); - if (!GetBattlerCoordsIndex(battlerId)) + switch (GetBattlerCoordsIndex(battler)) + { + case BATTLE_COORDS_SINGLES: tileNumAdder = 0x1A; - else + break; + default: tileNumAdder = 0x12; + break; + } } else { - status = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_STATUS); tileNumAdder = 0x11; } if (status & STATUS1_SLEEP) { - statusGfxPtr = GetBattleInterfaceGfxPtr(GetStatusIconForBattlerId(B_INTERFACE_GFX_STATUS_SLP_BATTLER0, battlerId)); + statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_SLP_BATTLER0, battler)); statusPalId = PAL_STATUS_SLP; } else if (status & STATUS1_PSN_ANY) { - statusGfxPtr = GetBattleInterfaceGfxPtr(GetStatusIconForBattlerId(B_INTERFACE_GFX_STATUS_PSN_BATTLER0, battlerId)); + statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_PSN_BATTLER0, battler)); statusPalId = PAL_STATUS_PSN; } else if (status & STATUS1_BURN) { - statusGfxPtr = GetBattleInterfaceGfxPtr(GetStatusIconForBattlerId(B_INTERFACE_GFX_STATUS_BRN_BATTLER0, battlerId)); + statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_BRN_BATTLER0, battler)); statusPalId = PAL_STATUS_BRN; } else if (status & STATUS1_FREEZE) { - statusGfxPtr = GetBattleInterfaceGfxPtr(GetStatusIconForBattlerId(B_INTERFACE_GFX_STATUS_FRZ_BATTLER0, battlerId)); + statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_FRZ_BATTLER0, battler)); statusPalId = PAL_STATUS_FRZ; } else if (status & STATUS1_FROSTBITE) { - statusGfxPtr = GetBattleInterfaceGfxPtr(GetStatusIconForBattlerId(B_INTERFACE_GFX_STATUS_FRB_BATTLER0, battlerId)); + statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_FRB_BATTLER0, battler)); statusPalId = PAL_STATUS_FRZ; } else if (status & STATUS1_PARALYSIS) { - statusGfxPtr = GetBattleInterfaceGfxPtr(GetStatusIconForBattlerId(B_INTERFACE_GFX_STATUS_PAR_BATTLER0, battlerId)); + statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_PRZ_BATTLER0, battler)); statusPalId = PAL_STATUS_PAR; } else { - statusGfxPtr = GetBattleInterfaceGfxPtr(B_INTERFACE_GFX_STATUS_NONE); + statusGfxPtr = GetHealthboxElementGfxPtr(HEALTHBOX_GFX_39); for (i = 0; i < 3; i++) - CpuCopy32(statusGfxPtr, - (void *)(OBJ_VRAM0 + (gSprites[healthboxSpriteId].oam.tileNum + tileNumAdder + i) * TILE_SIZE_4BPP), - 1 * TILE_SIZE_4BPP); + CpuCopy32(statusGfxPtr, (void *)(OBJ_VRAM0 + (gSprites[healthboxSpriteId].oam.tileNum + tileNumAdder + i) * TILE_SIZE_4BPP), 32); - if (!gBattleSpritesDataPtr->battlerData[battlerId].hpNumbersNoBars) - CpuCopy32(GetBattleInterfaceGfxPtr(B_INTERFACE_GFX_HP_BAR_HP_TEXT), - (void *)(OBJ_VRAM0 + gSprites[healthBarSpriteId].oam.tileNum * TILE_SIZE_4BPP), - 2 * TILE_SIZE_4BPP); + if (!gBattleSpritesDataPtr->battlerData[battler].hpNumbersNoBars) + CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_1), (void *)(OBJ_VRAM0 + gSprites[healthBarSpriteId].oam.tileNum * TILE_SIZE_4BPP), 64); TryAddPokeballIconToHealthbox(healthboxSpriteId, TRUE); return; } pltAdder = PLTT_ID(gSprites[healthboxSpriteId].oam.paletteNum); - pltAdder += battlerId + 12; + pltAdder += battler + 12; - FillPalette(sStatusIconColors[statusPalId], pltAdder + OBJ_PLTT_OFFSET, PLTT_SIZEOF(1)); + FillPalette(sStatusIconColors[statusPalId], OBJ_PLTT_OFFSET + pltAdder, PLTT_SIZEOF(1)); CpuCopy16(&gPlttBufferUnfaded[OBJ_PLTT_OFFSET + pltAdder], (u16 *)OBJ_PLTT + pltAdder, PLTT_SIZEOF(1)); - CpuCopy32(statusGfxPtr, (void *)(OBJ_VRAM0 + (gSprites[healthboxSpriteId].oam.tileNum + tileNumAdder) * TILE_SIZE_4BPP), 3 * TILE_SIZE_4BPP); - if (GetBattlerCoordsIndex(battlerId) == BATTLE_COORDS_DOUBLES || !IsOnPlayerSide(battlerId)) + CpuCopy32(statusGfxPtr, (void *)(OBJ_VRAM0 + (gSprites[healthboxSpriteId].oam.tileNum + tileNumAdder) * TILE_SIZE_4BPP), 96); + if (GetBattlerCoordsIndex(battler) == BATTLE_COORDS_DOUBLES || !IsOnPlayerSide(battler)) { - if (!gBattleSpritesDataPtr->battlerData[battlerId].hpNumbersNoBars) + if (!gBattleSpritesDataPtr->battlerData[battler].hpNumbersNoBars) { - CpuCopy32(GetBattleInterfaceGfxPtr(B_INTERFACE_GFX_TRANSPARENT), - (void *)(OBJ_VRAM0 + gSprites[healthBarSpriteId].oam.tileNum * TILE_SIZE_4BPP), - 1 * TILE_SIZE_4BPP); - CpuCopy32(GetBattleInterfaceGfxPtr(B_INTERFACE_GFX_HP_BAR_LEFT_BORDER), - (void *)(OBJ_VRAM0 + (gSprites[healthBarSpriteId].oam.tileNum + 1) * TILE_SIZE_4BPP), - 1 * TILE_SIZE_4BPP); + CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_0), (void *)(OBJ_VRAM0 + gSprites[healthBarSpriteId].oam.tileNum * TILE_SIZE_4BPP), 32); + CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_65), (void *)(OBJ_VRAM0 + (gSprites[healthBarSpriteId].oam.tileNum + 1) * TILE_SIZE_4BPP), 32); } } TryAddPokeballIconToHealthbox(healthboxSpriteId, FALSE); } -static u8 GetStatusIconForBattlerId(u8 statusElementId, u8 battlerId) +static u8 GetStatusIconForBattlerId(u8 statusElementId, enum BattlerId battler) { u8 ret = statusElementId; switch (statusElementId) { - case B_INTERFACE_GFX_STATUS_PSN_BATTLER0: - if (battlerId == B_BATTLER_0) - ret = B_INTERFACE_GFX_STATUS_PSN_BATTLER0; - else if (battlerId == B_BATTLER_1) - ret = B_INTERFACE_GFX_STATUS_PSN_BATTLER1; - else if (battlerId == B_BATTLER_2) - ret = B_INTERFACE_GFX_STATUS_PSN_BATTLER2; + case HEALTHBOX_GFX_STATUS_PSN_BATTLER0: + if (battler == 0) + ret = HEALTHBOX_GFX_STATUS_PSN_BATTLER0; + else if (battler == 1) + ret = HEALTHBOX_GFX_STATUS_PSN_BATTLER1; + else if (battler == 2) + ret = HEALTHBOX_GFX_STATUS_PSN_BATTLER2; else - ret = B_INTERFACE_GFX_STATUS_PSN_BATTLER3; + ret = HEALTHBOX_GFX_STATUS_PSN_BATTLER3; break; - case B_INTERFACE_GFX_STATUS_PAR_BATTLER0: - if (battlerId == 0) - ret = B_INTERFACE_GFX_STATUS_PAR_BATTLER0; - else if (battlerId == 1) - ret = B_INTERFACE_GFX_STATUS_PAR_BATTLER1; - else if (battlerId == 2) - ret = B_INTERFACE_GFX_STATUS_PAR_BATTLER2; + case HEALTHBOX_GFX_STATUS_PRZ_BATTLER0: + if (battler == 0) + ret = HEALTHBOX_GFX_STATUS_PRZ_BATTLER0; + else if (battler == 1) + ret = HEALTHBOX_GFX_STATUS_PRZ_BATTLER1; + else if (battler == 2) + ret = HEALTHBOX_GFX_STATUS_PRZ_BATTLER2; else - ret = B_INTERFACE_GFX_STATUS_PAR_BATTLER3; + ret = HEALTHBOX_GFX_STATUS_PRZ_BATTLER3; break; - case B_INTERFACE_GFX_STATUS_SLP_BATTLER0: - if (battlerId == 0) - ret = B_INTERFACE_GFX_STATUS_SLP_BATTLER0; - else if (battlerId == 1) - ret = B_INTERFACE_GFX_STATUS_SLP_BATTLER1; - else if (battlerId == 2) - ret = B_INTERFACE_GFX_STATUS_SLP_BATTLER2; + case HEALTHBOX_GFX_STATUS_SLP_BATTLER0: + if (battler == 0) + ret = HEALTHBOX_GFX_STATUS_SLP_BATTLER0; + else if (battler == 1) + ret = HEALTHBOX_GFX_STATUS_SLP_BATTLER1; + else if (battler == 2) + ret = HEALTHBOX_GFX_STATUS_SLP_BATTLER2; else - ret = B_INTERFACE_GFX_STATUS_SLP_BATTLER3; + ret = HEALTHBOX_GFX_STATUS_SLP_BATTLER3; break; - case B_INTERFACE_GFX_STATUS_FRZ_BATTLER0: - if (battlerId == 0) - ret = B_INTERFACE_GFX_STATUS_FRZ_BATTLER0; - else if (battlerId == 1) - ret = B_INTERFACE_GFX_STATUS_FRZ_BATTLER1; - else if (battlerId == 2) - ret = B_INTERFACE_GFX_STATUS_FRZ_BATTLER2; + case HEALTHBOX_GFX_STATUS_FRZ_BATTLER0: + if (battler == 0) + ret = HEALTHBOX_GFX_STATUS_FRZ_BATTLER0; + else if (battler == 1) + ret = HEALTHBOX_GFX_STATUS_FRZ_BATTLER1; + else if (battler == 2) + ret = HEALTHBOX_GFX_STATUS_FRZ_BATTLER2; else - ret = B_INTERFACE_GFX_STATUS_FRZ_BATTLER3; + ret = HEALTHBOX_GFX_STATUS_FRZ_BATTLER3; break; - case B_INTERFACE_GFX_STATUS_FRB_BATTLER0: - if (battlerId == 0) - ret = B_INTERFACE_GFX_STATUS_FRB_BATTLER0; - else if (battlerId == 1) - ret = B_INTERFACE_GFX_STATUS_FRB_BATTLER1; - else if (battlerId == 2) - ret = B_INTERFACE_GFX_STATUS_FRB_BATTLER2; + case HEALTHBOX_GFX_STATUS_FRB_BATTLER0: + if (battler == 0) + ret = HEALTHBOX_GFX_STATUS_FRB_BATTLER0; + else if (battler == 1) + ret = HEALTHBOX_GFX_STATUS_FRB_BATTLER1; + else if (battler == 2) + ret = HEALTHBOX_GFX_STATUS_FRB_BATTLER2; else - ret = B_INTERFACE_GFX_STATUS_FRB_BATTLER3; + ret = HEALTHBOX_GFX_STATUS_FRB_BATTLER3; break; - case B_INTERFACE_GFX_STATUS_BRN_BATTLER0: - if (battlerId == 0) - ret = B_INTERFACE_GFX_STATUS_BRN_BATTLER0; - else if (battlerId == 1) - ret = B_INTERFACE_GFX_STATUS_BRN_BATTLER1; - else if (battlerId == 2) - ret = B_INTERFACE_GFX_STATUS_BRN_BATTLER2; + case HEALTHBOX_GFX_STATUS_BRN_BATTLER0: + if (battler == 0) + ret = HEALTHBOX_GFX_STATUS_BRN_BATTLER0; + else if (battler == 1) + ret = HEALTHBOX_GFX_STATUS_BRN_BATTLER1; + else if (battler == 2) + ret = HEALTHBOX_GFX_STATUS_BRN_BATTLER2; else - ret = B_INTERFACE_GFX_STATUS_BRN_BATTLER3; + ret = HEALTHBOX_GFX_STATUS_BRN_BATTLER3; break; } return ret; @@ -1893,57 +1915,67 @@ static u8 GetStatusIconForBattlerId(u8 statusElementId, u8 battlerId) static void UpdateSafariBallsTextOnHealthbox(u8 healthboxSpriteId) { - u32 windowId, spriteTileNum; - u8 *windowTileData; + u32 healthboxSpriteId2 = gSprites[healthboxSpriteId].oam.affineParam; - windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(gText_SafariBalls, 0, 3, &windowId); - spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * TILE_SIZE_4BPP; - TextIntoHealthboxObject((void *)(OBJ_VRAM0 + 0x40) + spriteTileNum, windowTileData, 6); - TextIntoHealthboxObject((void *)(OBJ_VRAM0 + 0x800) + spriteTileNum, windowTileData + 0xC0, 2); - RemoveWindowOnHealthbox(windowId); + s16 savedValue1 = gSprites[healthboxSpriteId].data[1]; + s16 savedValue2 = gSprites[healthboxSpriteId2].data[1]; + gSprites[healthboxSpriteId].data[1] = healthboxSpriteId2; + gSprites[healthboxSpriteId2].data[1] = SPRITE_NONE; + + AddSpriteTextPrinterParameterized6(healthboxSpriteId, FONT_SMALL, 16, 3, 0, 0, sHealthBoxTextColor, 0, gText_SafariBalls); + + gSprites[healthboxSpriteId].data[1] = savedValue1; + gSprites[healthboxSpriteId2].data[1] = savedValue2; } static void UpdateLeftNoOfBallsTextOnHealthbox(u8 healthboxSpriteId) { u8 text[16]; u8 *txtPtr; - u32 windowId, spriteTileNum; - u8 *windowTileData; + + u32 healthboxSpriteId2 = gSprites[healthboxSpriteId].oam.affineParam; + + s16 savedValue1 = gSprites[healthboxSpriteId].data[1]; + s16 savedValue2 = gSprites[healthboxSpriteId2].data[1]; + gSprites[healthboxSpriteId].data[1] = healthboxSpriteId2; + gSprites[healthboxSpriteId2].data[1] = SPRITE_NONE; + txtPtr = StringCopy(text, gText_HighlightRed_Left); ConvertIntToDecimalStringN(txtPtr, gNumSafariBalls, STR_CONV_MODE_LEFT_ALIGN, 2); - windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, 47 - GetStringWidth(FONT_SMALL, text, 0), 3, &windowId); - spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * TILE_SIZE_4BPP; - SafariTextIntoHealthboxObject((void *)(OBJ_VRAM0 + 0x2C0) + spriteTileNum, windowTileData, 2); - SafariTextIntoHealthboxObject((void *)(OBJ_VRAM0 + 0xA00) + spriteTileNum, windowTileData + 0x40, 4); - RemoveWindowOnHealthbox(windowId); + FillSpriteRectColor(healthboxSpriteId, 53, 19, 31, 12, HEALTHBOX_BG_INDEX); + AddSpriteTextPrinterParameterized6(healthboxSpriteId, FONT_SMALL, 53, 19, 0, 0, sHealthBoxTextColor, 0, text); + + gSprites[healthboxSpriteId].data[1] = savedValue1; + gSprites[healthboxSpriteId2].data[1] = savedValue2; } void UpdateHealthboxAttribute(u8 healthboxSpriteId, struct Pokemon *mon, u8 elementId) { - u8 battlerId = gSprites[healthboxSpriteId].sBattlerId; + enum BattlerId battler = gSprites[healthboxSpriteId].hMain_Battler; s32 maxHp = GetMonData(mon, MON_DATA_MAX_HP); s32 currHp = GetMonData(mon, MON_DATA_HP); - if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + if (IsOnPlayerSide(battler)) { - u8 isDoubles = GetBattlerCoordsIndex(battlerId); + u8 isDoubles = GetBattlerCoordsIndex(battler) == BATTLE_COORDS_DOUBLES; if (elementId == HEALTHBOX_LEVEL || elementId == HEALTHBOX_ALL) UpdateLvlInHealthbox(healthboxSpriteId, GetMonData(mon, MON_DATA_LEVEL)); - - if (elementId == HEALTHBOX_CURRENT_HP || elementId == HEALTHBOX_ALL) - UpdateHpTextInHealthbox(healthboxSpriteId, HP_CURRENT, currHp, maxHp); - if (elementId == HEALTHBOX_MAX_HP || elementId == HEALTHBOX_ALL) + if (elementId == HEALTHBOX_ALL) + UpdateHpTextInHealthbox(healthboxSpriteId, HP_BOTH, currHp, maxHp); + else if (elementId == HEALTHBOX_MAX_HP) UpdateHpTextInHealthbox(healthboxSpriteId, HP_MAX, currHp, maxHp); + else if (elementId == HEALTHBOX_CURRENT_HP) + UpdateHpTextInHealthbox(healthboxSpriteId, HP_CURRENT, currHp, maxHp); if (elementId == HEALTHBOX_HEALTH_BAR || elementId == HEALTHBOX_ALL) { LoadBattleBarGfx(0); - SetBattleBarStruct(battlerId, healthboxSpriteId, maxHp, currHp, 0); - MoveBattleBar(battlerId, healthboxSpriteId, HEALTH_BAR, 0); + SetBattleBarStruct(battler, healthboxSpriteId, maxHp, currHp, 0); + MoveBattleBar(battler, healthboxSpriteId, HEALTH_BAR, 0); } if (!isDoubles && (elementId == HEALTHBOX_EXP_BAR || elementId == HEALTHBOX_ALL)) @@ -1960,8 +1992,8 @@ void UpdateHealthboxAttribute(u8 healthboxSpriteId, struct Pokemon *mon, u8 elem currLevelExp = gExperienceTables[gSpeciesInfo[species].growthRate][level]; currExpBarValue = exp - currLevelExp; maxExpBarValue = gExperienceTables[gSpeciesInfo[species].growthRate][level + 1] - currLevelExp; - SetBattleBarStruct(battlerId, healthboxSpriteId, maxExpBarValue, currExpBarValue, isDoubles); - MoveBattleBar(battlerId, healthboxSpriteId, EXP_BAR, 0); + SetBattleBarStruct(battler, healthboxSpriteId, maxExpBarValue, currExpBarValue, isDoubles); + MoveBattleBar(battler, healthboxSpriteId, EXP_BAR, 0); } if (elementId == HEALTHBOX_NICK || elementId == HEALTHBOX_ALL) UpdateNickInHealthbox(healthboxSpriteId, mon); @@ -1976,13 +2008,20 @@ void UpdateHealthboxAttribute(u8 healthboxSpriteId, struct Pokemon *mon, u8 elem { if (elementId == HEALTHBOX_LEVEL || elementId == HEALTHBOX_ALL) UpdateLvlInHealthbox(healthboxSpriteId, GetMonData(mon, MON_DATA_LEVEL)); + if (gBattleSpritesDataPtr->battlerData[battler].hpNumbersNoBars) + { + if (elementId == HEALTHBOX_ALL) + UpdateHpTextInHealthbox(healthboxSpriteId, HP_BOTH, currHp, maxHp); + else if (elementId == HEALTHBOX_MAX_HP) + UpdateHpTextInHealthbox(healthboxSpriteId, HP_MAX, currHp, maxHp); + else if (elementId == HEALTHBOX_CURRENT_HP) + UpdateHpTextInHealthbox(healthboxSpriteId, HP_CURRENT, currHp, maxHp); + } if (elementId == HEALTHBOX_HEALTH_BAR || elementId == HEALTHBOX_ALL) { LoadBattleBarGfx(0); - maxHp = GetMonData(mon, MON_DATA_MAX_HP); - currHp = GetMonData(mon, MON_DATA_HP); - SetBattleBarStruct(battlerId, healthboxSpriteId, maxHp, currHp, 0); - MoveBattleBar(battlerId, healthboxSpriteId, HEALTH_BAR, 0); + SetBattleBarStruct(battler, healthboxSpriteId, maxHp, currHp, 0); + MoveBattleBar(battler, healthboxSpriteId, HEALTH_BAR, 0); } if (elementId == HEALTHBOX_NICK || elementId == HEALTHBOX_ALL) UpdateNickInHealthbox(healthboxSpriteId, mon); @@ -1991,112 +2030,131 @@ void UpdateHealthboxAttribute(u8 healthboxSpriteId, struct Pokemon *mon, u8 elem } } -#define B_HEALTHBAR_NUM_PIXELS 48 -#define B_HEALTHBAR_NUM_TILES (B_HEALTHBAR_NUM_PIXELS / 8) -#define B_EXPBAR_NUM_PIXELS 64 -#define B_EXPBAR_NUM_TILES (B_EXPBAR_NUM_PIXELS / 8) +#define B_EXPBAR_PIXELS 64 +#define B_HEALTHBAR_PIXELS 48 -s32 MoveBattleBar(u8 battlerId, u8 healthboxSpriteId, u8 whichBar, u8 unused) +s32 MoveBattleBar(enum BattlerId battler, u8 healthboxSpriteId, u8 whichBar, u8 unused) { s32 currentBarValue; - if (whichBar == HEALTH_BAR) + if (whichBar == HEALTH_BAR) // health bar { - u16 hpFraction = B_FAST_HP_DRAIN == FALSE ? 1 : max(gBattleSpritesDataPtr->battleBars[battlerId].maxValue / B_HEALTHBAR_NUM_PIXELS, 1); - currentBarValue = CalcNewBarValue(gBattleSpritesDataPtr->battleBars[battlerId].maxValue, - gBattleSpritesDataPtr->battleBars[battlerId].oldValue, - gBattleSpritesDataPtr->battleBars[battlerId].receivedValue, - &gBattleSpritesDataPtr->battleBars[battlerId].currValue, - B_HEALTHBAR_NUM_TILES, - hpFraction); + u16 hpFraction = B_FAST_HP_DRAIN == FALSE ? 1 : max(gBattleSpritesDataPtr->battleBars[battler].maxValue / (B_HEALTHBAR_PIXELS / 2), 1); + currentBarValue = CalcNewBarValue(gBattleSpritesDataPtr->battleBars[battler].maxValue, + gBattleSpritesDataPtr->battleBars[battler].oldValue, + gBattleSpritesDataPtr->battleBars[battler].receivedValue, + &gBattleSpritesDataPtr->battleBars[battler].currValue, + B_HEALTHBAR_PIXELS / 8, hpFraction); } else // exp bar { - u16 expFraction = GetScaledExpFraction(gBattleSpritesDataPtr->battleBars[battlerId].oldValue, - gBattleSpritesDataPtr->battleBars[battlerId].receivedValue, - gBattleSpritesDataPtr->battleBars[battlerId].maxValue, B_EXPBAR_NUM_TILES); - + u16 expFraction = GetScaledExpFraction(gBattleSpritesDataPtr->battleBars[battler].oldValue, + gBattleSpritesDataPtr->battleBars[battler].receivedValue, + gBattleSpritesDataPtr->battleBars[battler].maxValue, 8); if (expFraction == 0) expFraction = 1; - expFraction = abs(gBattleSpritesDataPtr->battleBars[battlerId].receivedValue / expFraction); + expFraction = abs(gBattleSpritesDataPtr->battleBars[battler].receivedValue / expFraction); - currentBarValue = CalcNewBarValue(gBattleSpritesDataPtr->battleBars[battlerId].maxValue, - gBattleSpritesDataPtr->battleBars[battlerId].oldValue, - gBattleSpritesDataPtr->battleBars[battlerId].receivedValue, - &gBattleSpritesDataPtr->battleBars[battlerId].currValue, - B_EXPBAR_NUM_TILES, - expFraction); + currentBarValue = CalcNewBarValue(gBattleSpritesDataPtr->battleBars[battler].maxValue, + gBattleSpritesDataPtr->battleBars[battler].oldValue, + gBattleSpritesDataPtr->battleBars[battler].receivedValue, + &gBattleSpritesDataPtr->battleBars[battler].currValue, + B_EXPBAR_PIXELS / 8, expFraction); } - if (whichBar == EXP_BAR || (whichBar == HEALTH_BAR && !gBattleSpritesDataPtr->battlerData[battlerId].hpNumbersNoBars)) - MoveBattleBarGraphically(battlerId, whichBar); + if (whichBar == EXP_BAR || (whichBar == HEALTH_BAR && !gBattleSpritesDataPtr->battlerData[battler].hpNumbersNoBars)) + MoveBattleBarGraphically(battler, whichBar); if (currentBarValue == -1) - gBattleSpritesDataPtr->battleBars[battlerId].currValue = 0; + gBattleSpritesDataPtr->battleBars[battler].currValue = 0; return currentBarValue; } -static void MoveBattleBarGraphically(u8 battlerId, u8 whichBar) +static void MoveBattleBarGraphically(enum BattlerId battler, u8 whichBar) { - u8 filledPixels[B_HEALTHBAR_NUM_TILES > B_EXPBAR_NUM_TILES ? B_HEALTHBAR_NUM_TILES : B_EXPBAR_NUM_TILES]; - u8 totalFilledPixels, level; + u8 array[8]; + u8 level; u8 barElementId; u8 i; + s32 currValue, maxValue; switch (whichBar) { case HEALTH_BAR: - totalFilledPixels = CalcBarFilledPixels(gBattleSpritesDataPtr->battleBars[battlerId].maxValue, - gBattleSpritesDataPtr->battleBars[battlerId].oldValue, - gBattleSpritesDataPtr->battleBars[battlerId].receivedValue, - &gBattleSpritesDataPtr->battleBars[battlerId].currValue, - filledPixels, - B_HEALTHBAR_NUM_TILES); - - if (totalFilledPixels > (B_HEALTHBAR_NUM_PIXELS * 50 / 100)) // more than 50 % hp - barElementId = B_INTERFACE_GFX_HP_BAR_GREEN; - else if (totalFilledPixels > (B_HEALTHBAR_NUM_PIXELS * 20 / 100)) // more than 20% hp - barElementId = B_INTERFACE_GFX_HP_BAR_YELLOW; - else - barElementId = B_INTERFACE_GFX_HP_BAR_RED; // 20 % or less - - for (i = 0; i < B_HEALTHBAR_NUM_TILES; i++) + if (B_HPBAR_COLOR_THRESHOLD < GEN_5) { - u8 healthbarSpriteId = gSprites[gBattleSpritesDataPtr->battleBars[battlerId].healthboxSpriteId].sHealthBarSpriteId; - if (i < 2) // first 2 tiles are on left healthbar sprite - CpuCopy32(GetBattleInterfaceGfxPtr(barElementId) + filledPixels[i] * TILE_SIZE_4BPP, - (void *)(OBJ_VRAM0 + (gSprites[healthbarSpriteId].oam.tileNum + 2 + i) * TILE_SIZE_4BPP), // + 2 here is due to B_INTERFACE_GFX_HP_BAR_HP_TEXT - 1 * TILE_SIZE_4BPP); - else // remaining 4 tiles are on right healthbar sprite - CpuCopy32(GetBattleInterfaceGfxPtr(barElementId) + filledPixels[i] * TILE_SIZE_4BPP, - (void *)(OBJ_VRAM0 + 64 + (i + gSprites[healthbarSpriteId].oam.tileNum) * TILE_SIZE_4BPP), - 1 * TILE_SIZE_4BPP); + maxValue = B_HEALTHBAR_PIXELS; + currValue = CalcBarFilledPixels(gBattleSpritesDataPtr->battleBars[battler].maxValue, + gBattleSpritesDataPtr->battleBars[battler].oldValue, + gBattleSpritesDataPtr->battleBars[battler].receivedValue, + &gBattleSpritesDataPtr->battleBars[battler].currValue, + array, B_HEALTHBAR_PIXELS / 8); + } + else + { + CalcBarFilledPixels(gBattleSpritesDataPtr->battleBars[battler].maxValue, + gBattleSpritesDataPtr->battleBars[battler].oldValue, + gBattleSpritesDataPtr->battleBars[battler].receivedValue, + &gBattleSpritesDataPtr->battleBars[battler].currValue, + array, B_HEALTHBAR_PIXELS / 8); + + maxValue = gBattleSpritesDataPtr->battleBars[battler].maxValue; + currValue = gBattleSpritesDataPtr->battleBars[battler].currValue; + + if (maxValue < B_HEALTHBAR_PIXELS) + currValue = Q_24_8_TO_INT(currValue); + } + + switch (GetHPBarLevel(currValue, maxValue)) + { + case HP_BAR_FULL: + case HP_BAR_GREEN: + barElementId = HEALTHBOX_GFX_HP_BAR_GREEN; + break; + case HP_BAR_YELLOW: + barElementId = HEALTHBOX_GFX_HP_BAR_YELLOW; + break; + default: + case HP_BAR_RED: + if (maxValue > 1) // handling for wonder guard + barElementId = HEALTHBOX_GFX_HP_BAR_RED; + else + barElementId = HEALTHBOX_GFX_HP_BAR_GREEN; + break; + } + + for (i = 0; i < 6; i++) + { + u8 healthbarSpriteId = gSprites[gBattleSpritesDataPtr->battleBars[battler].healthboxSpriteId].hMain_HealthBarSpriteId; + if (i < 2) + CpuCopy32(GetHealthboxElementGfxPtr(barElementId) + array[i] * 32, + (void *)(OBJ_VRAM0 + (gSprites[healthbarSpriteId].oam.tileNum + 2 + i) * TILE_SIZE_4BPP), 32); + else + CpuCopy32(GetHealthboxElementGfxPtr(barElementId) + array[i] * 32, + (void *)(OBJ_VRAM0 + 64 + (i + gSprites[healthbarSpriteId].oam.tileNum) * TILE_SIZE_4BPP), 32); } break; case EXP_BAR: - CalcBarFilledPixels(gBattleSpritesDataPtr->battleBars[battlerId].maxValue, - gBattleSpritesDataPtr->battleBars[battlerId].oldValue, - gBattleSpritesDataPtr->battleBars[battlerId].receivedValue, - &gBattleSpritesDataPtr->battleBars[battlerId].currValue, - filledPixels, - B_EXPBAR_NUM_TILES); - level = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_LEVEL); - if (level == MAX_LEVEL) + CalcBarFilledPixels(gBattleSpritesDataPtr->battleBars[battler].maxValue, + gBattleSpritesDataPtr->battleBars[battler].oldValue, + gBattleSpritesDataPtr->battleBars[battler].receivedValue, + &gBattleSpritesDataPtr->battleBars[battler].currValue, + array, B_EXPBAR_PIXELS / 8); + level = GetMonData(GetBattlerMon(battler), MON_DATA_LEVEL); + if (level >= MAX_LEVEL) { - for (i = 0; i < B_EXPBAR_NUM_TILES; i++) - filledPixels[i] = 0; + for (i = 0; i < 8; i++) + array[i] = 0; } - for (i = 0; i < B_EXPBAR_NUM_TILES; i++) + for (i = 0; i < 8; i++) { - if (i < 4) // first 4 tiles are on left healthbox sprite - CpuCopy32(GetBattleInterfaceGfxPtr(B_INTERFACE_GFX_EXP_BAR) + filledPixels[i] * TILE_SIZE_4BPP, - (void *)(OBJ_VRAM0 + (gSprites[gBattleSpritesDataPtr->battleBars[battlerId].healthboxSpriteId].oam.tileNum + 36 + i) * TILE_SIZE_4BPP), - 1 * TILE_SIZE_4BPP); - else // remaining 4 tiles are on right healthbox sprite - CpuCopy32(GetBattleInterfaceGfxPtr(B_INTERFACE_GFX_EXP_BAR) + filledPixels[i] * TILE_SIZE_4BPP, - (void *)(OBJ_VRAM0 + 0xB80 + (i + gSprites[gBattleSpritesDataPtr->battleBars[battlerId].healthboxSpriteId].oam.tileNum) * TILE_SIZE_4BPP), - 1 * TILE_SIZE_4BPP); + if (i < 4) + CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_12) + array[i] * 32, + (void *)(OBJ_VRAM0 + (gSprites[gBattleSpritesDataPtr->battleBars[battler].healthboxSpriteId].oam.tileNum + 0x24 + i) * TILE_SIZE_4BPP), 32); + else + CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_12) + array[i] * 32, + (void *)(OBJ_VRAM0 + 0xB80 + (i + gSprites[gBattleSpritesDataPtr->battleBars[battler].healthboxSpriteId].oam.tileNum) * TILE_SIZE_4BPP), 32); } break; } @@ -2115,12 +2173,7 @@ static s32 CalcNewBarValue(s32 maxValue, s32 oldValue, s32 receivedValue, s32 *c *currValue = oldValue; } - newValue = oldValue - receivedValue; - if (newValue < 0) - newValue = 0; - else if (newValue > maxValue) - newValue = maxValue; - + newValue = SubtractClamped(HP_EMPTY, maxValue, oldValue, receivedValue); if (maxValue < scale) { if (newValue == Q_24_8_TO_INT(*currValue) && (*currValue & 0xFF) == 0) @@ -2181,50 +2234,48 @@ static s32 CalcNewBarValue(s32 maxValue, s32 oldValue, s32 receivedValue, s32 *c return ret; } -static u8 CalcBarFilledPixels(s32 maxValue, s32 oldValue, s32 receivedValue, s32 *currValue, u8 *filledPixels, u8 numTiles) +static u8 CalcBarFilledPixels(s32 maxValue, s32 oldValue, s32 receivedValue, s32 *currValue, u8 *pixelsArray, u8 scale) { - u8 numPixelsToFill, totalFilledPixels, totalPixels; + u8 pixels, filledPixels, totalPixels; u8 i; - s32 newValue = oldValue - receivedValue; - if (newValue < 0) - newValue = 0; - else if (newValue > maxValue) - newValue = maxValue; + s32 newValue = SubtractClamped(HP_EMPTY, maxValue, oldValue, receivedValue); + totalPixels = scale * 8; - totalPixels = numTiles * 8; - - for (i = 0; i < numTiles; i++) - filledPixels[i] = 0; + for (i = 0; i < scale; i++) + pixelsArray[i] = 0; + // Safe Div, because 2vs1 battles can have maxValue 0. if (maxValue < totalPixels) - numPixelsToFill = Q_24_8_TO_INT(*currValue * totalPixels / maxValue); + pixels = SAFE_DIV(*currValue * totalPixels, maxValue) >> 8; else - numPixelsToFill = *currValue * totalPixels / maxValue; + pixels = SAFE_DIV(*currValue * totalPixels, maxValue); - totalFilledPixels = numPixelsToFill; + filledPixels = pixels; - if (numPixelsToFill == 0 && newValue > 0) + if (filledPixels == 0 && newValue > 0) { - filledPixels[0] = 1; - totalFilledPixels = 1; + pixelsArray[0] = 1; + filledPixels = 1; } else { - for (i = 0; i < numTiles; i++) + for (i = 0; i < scale; i++) { - if (numPixelsToFill >= 8) // too many to fill into a single tile - filledPixels[i] = 8; + if (pixels >= 8) + { + pixelsArray[i] = 8; + } else { - filledPixels[i] = numPixelsToFill; + pixelsArray[i] = pixels; break; } - numPixelsToFill -= 8; + pixels -= 8; } } - return totalFilledPixels; + return filledPixels; } static u8 GetScaledExpFraction(s32 oldValue, s32 receivedValue, s32 maxValue, u8 scale) @@ -2233,12 +2284,7 @@ static u8 GetScaledExpFraction(s32 oldValue, s32 receivedValue, s32 maxValue, u8 s8 oldToMax, newToMax; scale *= (B_FAST_EXP_GROW) ? 2 : 8; - newVal = oldValue - receivedValue; - - if (newVal < 0) - newVal = 0; - else if (newVal > maxValue) - newVal = maxValue; + newVal = SubtractClamped(HP_EMPTY, maxValue, oldValue, receivedValue); oldToMax = oldValue * scale / maxValue; newToMax = newVal * scale / maxValue; @@ -2259,83 +2305,37 @@ u8 GetScaledHPFraction(s16 hp, s16 maxhp, u8 scale) u8 GetHPBarLevel(s16 hp, s16 maxhp) { - u8 result; + s32 currValue, maxValue; if (hp == maxhp) - result = HP_BAR_FULL; + return HP_BAR_FULL; + + if (B_HPBAR_COLOR_THRESHOLD < GEN_5) + { + currValue = GetScaledHPFraction(hp, maxhp, B_HEALTHBAR_PIXELS); + maxValue = B_HEALTHBAR_PIXELS; + } else { - u8 fraction = GetScaledHPFraction(hp, maxhp, B_HEALTHBAR_NUM_PIXELS); - if (fraction > (B_HEALTHBAR_NUM_PIXELS * 50 / 100)) - result = HP_BAR_GREEN; - else if (fraction > (B_HEALTHBAR_NUM_PIXELS * 20 / 100)) - result = HP_BAR_YELLOW; - else if (fraction > 0) - result = HP_BAR_RED; - else - result = HP_BAR_EMPTY; + currValue = hp; + maxValue = maxhp; } - return result; + if (currValue > (maxValue * 50 / 100)) // more than 50% hp + return HP_BAR_GREEN; + else if (currValue > (maxValue * 20 / 100)) // more than 20% hp + return HP_BAR_YELLOW; + else if (currValue > 0) + return HP_BAR_RED; // 20% or less + + return HP_BAR_EMPTY; } -static const struct WindowTemplate sHealthboxWindowTemplate = { - .bg = 0, - .tilemapLeft = 0, - .tilemapTop = 0, - .width = 8, - .height = 2, - .paletteNum = 0, - .baseBlock = 0 -}; - -static u8 *AddTextPrinterAndCreateWindowOnHealthbox(const u8 *str, u32 x, u32 y, u32 *windowId) +static void FillHealthboxObject(void *dest, u32 valMult, u32 numTiles) { - u16 winId; - u8 color[3]; - struct WindowTemplate winTemplate = sHealthboxWindowTemplate; - - winId = AddWindow(&winTemplate); - FillWindowPixelBuffer(winId, PIXEL_FILL(2)); - - color[0] = 2; - color[1] = 1; - color[2] = 3; - - AddTextPrinterParameterized4(winId, FONT_SMALL, x, y, 0, 0, color, -1, str); - - *windowId = winId; - return (u8 *)(GetWindowAttribute(winId, WINDOW_TILE_DATA)); + CpuFill32(0x11111111 * valMult, dest, numTiles * TILE_SIZE_4BPP); } -static void RemoveWindowOnHealthbox(u32 windowId) -{ - RemoveWindow(windowId); -} - -static void TextIntoHealthboxObject(void *dest, u8 *windowTileData, s32 windowWidth) -{ - CpuCopy32(windowTileData + 256, dest + 256, windowWidth * TILE_SIZE_4BPP); -// + 256 as that prevents the top 4 blank rows of sHealthboxWindowTemplate from being copied - if (windowWidth > 0) - { - do - { - CpuCopy32(windowTileData + 20, dest + 20, 12); - dest += 32, windowTileData += 32; - windowWidth--; - } while (windowWidth != 0); - } -} - -static void SafariTextIntoHealthboxObject(void *dest, u8 *windowTileData, u32 windowWidth) -{ - CpuCopy32(windowTileData, dest, windowWidth * TILE_SIZE_4BPP); - CpuCopy32(windowTileData + 256, dest + 256, windowWidth * TILE_SIZE_4BPP); -} - -#undef sBattlerId - #define ABILITY_POP_UP_POS_X_DIFF 64 #define ABILITY_POP_UP_POS_X_SLIDE 128 #define ABILITY_POP_UP_POS_X_SPEED 4 @@ -2415,9 +2415,6 @@ static const struct SpriteTemplate sSpriteTemplate_AbilityPopUp = .tileTag = TAG_NONE, // Changed on the fly. .paletteTag = TAG_ABILITY_POP_UP, .oam = &sOamData_AbilityPopUp, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCb_AbilityPopUp }; @@ -2477,7 +2474,7 @@ static void TextIntoAbilityPopUp(void *dest, u8 *windowTileData, s32 windowWidth #undef PIXELS } -static void PrintOnAbilityPopUp(const u8 *str, u8 *spriteTileData1, u8 *spriteTileData2, u32 x, u32 y, u32 bgColor, u32 fgColor, u32 shadowColor, u32 printNickname, u32 battler) +static void PrintOnAbilityPopUp(const u8 *str, u8 *spriteTileData1, u8 *spriteTileData2, u32 x, u32 y, u32 bgColor, u32 fgColor, u32 shadowColor, u32 printNickname, enum BattlerId battler) { u32 windowId, fontId; u8 *windowTileData = AddTextPrinterAndCreateWindowOnAbilityPopUp(str, x, y, bgColor, fgColor, shadowColor, &windowId); @@ -2503,7 +2500,7 @@ static void PrintOnAbilityPopUp(const u8 *str, u8 *spriteTileData1, u8 *spriteTi RemoveWindow(windowId); } -static void PrintBattlerOnAbilityPopUp(u8 battler, u8 spriteId1, u8 spriteId2) +static void PrintBattlerOnAbilityPopUp(enum BattlerId battler, u8 spriteId1, u8 spriteId2) { u32 totalChar = 0, lastChar; struct Pokemon *illusionMon = GetIllusionMonPtr(battler); @@ -2548,7 +2545,7 @@ static void PrintAbilityOnAbilityPopUp(enum Ability ability, u8 spriteId1, u8 sp static inline bool32 IsAnyAbilityPopUpActive(void) { u32 activeAbilityPopUps = 0; - for (u32 battler = 0; battler < gBattlersCount; battler++) + for (enum BattlerId battler = 0; battler < gBattlersCount; battler++) { if (gBattleStruct->battlerState[battler].activeAbilityPopUps) activeAbilityPopUps++; @@ -2557,10 +2554,11 @@ static inline bool32 IsAnyAbilityPopUpActive(void) return activeAbilityPopUps; } -void CreateAbilityPopUp(u8 battler, enum Ability ability, bool32 isDoubleBattle) +void CreateAbilityPopUp(enum BattlerId battler, enum Ability ability, bool32 isDoubleBattle) { u8 *spriteIds; - u32 xSlide, tileTag, battlerPosition = GetBattlerPosition(battler); + u32 xSlide, tileTag; + enum BattlerPosition battlerPosition = GetBattlerPosition(battler); struct SpriteTemplate template; const s16 (*coords)[2]; @@ -2619,7 +2617,7 @@ void CreateAbilityPopUp(u8 battler, enum Ability ability, bool32 isDoubleBattle) PrintAbilityOnAbilityPopUp(ability, spriteIds[0], spriteIds[1]); } -void UpdateAbilityPopup(u8 battler) +void UpdateAbilityPopup(enum BattlerId battler) { u8 *spriteIds = gBattleStruct->abilityPopUpSpriteIds[battler]; enum Ability ability = (gBattleScripting.abilityPopupOverwrite) ? gBattleScripting.abilityPopupOverwrite @@ -2630,7 +2628,7 @@ void UpdateAbilityPopup(u8 battler) static void SpriteCb_AbilityPopUp(struct Sprite *sprite) { s16 *data = sprite->data; - u32 battlerPosition = GetBattlerPosition(sBattlerId); + enum BattlerPosition battlerPosition = GetBattlerPosition(sBattlerId); u32 fullX = sprite->x + sprite->x2; u32 speed; @@ -2648,11 +2646,11 @@ static void SpriteCb_AbilityPopUp(struct Sprite *sprite) xCoord += ABILITY_POP_UP_POS_X_DIFF; if (fullX == xCoord) - { + { sTimer = ABILITY_POP_UP_WAIT_FRAMES; sState = APU_STATE_IDLE; break; - } + } speed = sIsPlayerSide ? ABILITY_POP_UP_POS_X_SPEED : -ABILITY_POP_UP_POS_X_SPEED; sprite->x2 += speed; @@ -2674,10 +2672,10 @@ static void SpriteCb_AbilityPopUp(struct Sprite *sprite) case APU_STATE_SLIDE_OUT: { if (fullX == sprite->x) - { + { sState = APU_STATE_END; break; - } + } speed = sIsPlayerSide ? -ABILITY_POP_UP_POS_X_SPEED : ABILITY_POP_UP_POS_X_SPEED; sprite->x2 += speed; @@ -2694,7 +2692,7 @@ static void SpriteCb_AbilityPopUp(struct Sprite *sprite) } } -void DestroyAbilityPopUp(u8 battler) +void DestroyAbilityPopUp(enum BattlerId battler) { if (gBattleStruct->battlerState[battler].activeAbilityPopUps) { @@ -2707,7 +2705,7 @@ static void Task_FreeAbilityPopUpGfx(u8 taskId) { if (!IsAnyAbilityPopUpActive()) { - for (u32 battler = 0; battler < gBattlersCount; battler++) + for (enum BattlerId battler = 0; battler < gBattlersCount; battler++) { if (IndexOfSpriteTileTag(TAG_ABILITY_POP_UP_PLAYER1 + battler) != 0xFF) FreeSpriteTilesByTag(TAG_ABILITY_POP_UP_PLAYER1 + battler); @@ -2748,9 +2746,6 @@ static const struct SpriteTemplate sSpriteTemplate_LastUsedBallWindow = .tileTag = TAG_LAST_BALL_WINDOW, .paletteTag = TAG_ABILITY_POP_UP, .oam = &sOamData_LastUsedBall, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCB_LastUsedBallWin }; @@ -2778,9 +2773,6 @@ static const struct SpriteTemplate sSpriteTemplate_MoveInfoWindow = .tileTag = MOVE_INFO_WINDOW_TAG, .paletteTag = TAG_ABILITY_POP_UP, .oam = &sOamData_MoveInfoWindow, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCB_MoveInfoWin }; @@ -2893,7 +2885,8 @@ void TryAddLastUsedBallItemSprites(void) static void DestroyLastUsedBallWinGfx(struct Sprite *sprite) { FreeSpriteTilesByTag(TAG_LAST_BALL_WINDOW); - FreeSpritePaletteByTag(TAG_ABILITY_POP_UP); + if (GetSpriteTileStartByTag(MOVE_INFO_WINDOW_TAG) == 0xFFFF) + FreeSpritePaletteByTag(TAG_ABILITY_POP_UP); DestroySprite(sprite); gBattleStruct->ballSpriteIds[1] = MAX_SPRITES; } @@ -2911,6 +2904,9 @@ void TryToAddMoveInfoWindow(void) if (!B_SHOW_MOVE_DESCRIPTION) return; + if (B_MOVE_DESCRIPTION_BUTTON == L_BUTTON && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A) + return; + LoadSpritePalette(&sSpritePalette_AbilityPopUp); if (GetSpriteTileStartByTag(MOVE_INFO_WINDOW_TAG) == 0xFFFF) LoadSpriteSheet(&sSpriteSheet_MoveInfoWindow); @@ -2930,7 +2926,8 @@ void TryToHideMoveInfoWindow(void) static void DestroyMoveInfoWinGfx(struct Sprite *sprite) { FreeSpriteTilesByTag(MOVE_INFO_WINDOW_TAG); - FreeSpritePaletteByTag(TAG_ABILITY_POP_UP); + if (GetSpriteTileStartByTag(TAG_LAST_BALL_WINDOW) == 0xFFFF) + FreeSpritePaletteByTag(TAG_ABILITY_POP_UP); DestroySprite(sprite); gBattleStruct->moveInfoSpriteId = MAX_SPRITES; } @@ -3019,6 +3016,9 @@ static void TryHideOrRestoreLastUsedBall(u8 caseId) void TryHideLastUsedBall(void) { + if (B_LAST_USED_BALL_BUTTON == L_BUTTON && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A) + return; + if (B_LAST_USED_BALL == TRUE) TryHideOrRestoreLastUsedBall(0); } @@ -3028,6 +3028,9 @@ void TryRestoreLastUsedBall(void) if (B_LAST_USED_BALL == FALSE) return; + if (B_LAST_USED_BALL_BUTTON == L_BUTTON && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A) + return; + if (gBattleStruct->ballSpriteIds[0] != MAX_SPRITES) TryHideOrRestoreLastUsedBall(1); else @@ -3058,7 +3061,7 @@ static void Task_BounceBall(u8 taskId) { struct Sprite *sprite = &gSprites[gBattleStruct->ballSpriteIds[0]]; struct Task *task = &gTasks[taskId]; - switch(task->sState) + switch (task->sState) { case 0: // Bounce up sprite->sBounce = TRUE; @@ -3093,7 +3096,7 @@ static void Task_BounceBall(u8 taskId) } break; case 4: // Destroy Task - if(!sprite->sMoving) + if (!sprite->sMoving) { sprite->callback = SpriteCB_LastUsedBall; DestroyTask(taskId); diff --git a/src/battle_message.c b/src/battle_message.c index 48c2debff..76c5b00a5 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -189,7 +189,10 @@ const u8 gText_BattleSwitchWhich2[] = _("{PALETTE 5}{COLOR_HIGHLIGHT_SHADOW DYNA const u8 gText_BattleSwitchWhich3[] = _("{UP_ARROW}"); const u8 gText_BattleSwitchWhich4[] = _("{ESCAPE 4}"); const u8 gText_BattleSwitchWhich5[] = _("-"); -const u8 gText_SafariBalls[] = _("{HIGHLIGHT DARK_GRAY}SAFARI BALLS"); +const u8 gText_SafariBalls[] = _("SAFARI BALLS"); +const u8 gText_HealthboxGender_Male[] = _("{COLOR DYNAMIC_COLOR2}♂"); +const u8 gText_HealthboxGender_Female[] = _("{COLOR DYNAMIC_COLOR1}♀"); +const u8 gText_HealthboxGender_None[] = _("{COLOR DYNAMIC_COLOR2}"); const u8 gText_SafariBallLeft[] = _("{HIGHLIGHT DARK_GRAY}Left: $" "{HIGHLIGHT DARK_GRAY}"); const u8 gText_Sleep[] = _("sleep"); const u8 gText_Poison[] = _("poison"); diff --git a/src/data/graphics/gimmicks.h b/src/data/graphics/gimmicks.h index 06cff2d48..e75fa0212 100644 --- a/src/data/graphics/gimmicks.h +++ b/src/data/graphics/gimmicks.h @@ -65,8 +65,6 @@ static const struct SpriteTemplate sSpriteTemplate_GimmickTrigger = .paletteTag = TAG_GIMMICK_TRIGGER_PAL, .oam = &sOamData_GimmickTrigger, .anims = sSpriteAnimTable_GimmickTrigger, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCb_GimmickTrigger, }; @@ -153,9 +151,6 @@ static const struct SpriteTemplate sSpriteTemplate_BattlerIndicators[] = .tileTag = BATTLER_INDICATOR_TAG, // updated dynamically .paletteTag = TAG_TERA_INDICATOR_PAL, // updated dynamically .oam = &sOamData_GimmickIndicator, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCb_GimmickIndicator, }, [1] = @@ -163,9 +158,6 @@ static const struct SpriteTemplate sSpriteTemplate_BattlerIndicators[] = .tileTag = BATTLER_INDICATOR_TAG + 1, // updated dynamically .paletteTag = TAG_TERA_INDICATOR_PAL, // updated dynamically .oam = &sOamData_GimmickIndicator, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCb_GimmickIndicator, }, [2] = @@ -173,9 +165,6 @@ static const struct SpriteTemplate sSpriteTemplate_BattlerIndicators[] = .tileTag = BATTLER_INDICATOR_TAG + 2, // updated dynamically .paletteTag = TAG_TERA_INDICATOR_PAL, // updated dynamically .oam = &sOamData_GimmickIndicator, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCb_GimmickIndicator, }, [3] = @@ -183,9 +172,6 @@ static const struct SpriteTemplate sSpriteTemplate_BattlerIndicators[] = .tileTag = BATTLER_INDICATOR_TAG + 3, // updated dynamically .paletteTag = TAG_TERA_INDICATOR_PAL, // updated dynamically .oam = &sOamData_GimmickIndicator, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCb_GimmickIndicator, }, }; diff --git a/src/graphics.c b/src/graphics.c index 0d9eb4d75..1a9967cf9 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -417,8 +417,8 @@ const u32 gUnusedGfx_BasicFrame[] = INCBIN_U32("graphics/unused/basic_frame.4bpp const u16 gUnusedPal_BasicFrame[] = INCBIN_U16("graphics/unused/basic_frame.gbapal"); const u32 gUnusedTilemap_BasicFrame[] = INCBIN_U32("graphics/unused/basic_frame.bin.smolTM"); -const u16 gBattleInterface_Healthbox_Pal[] = INCBIN_U16("graphics/battle_interface/healthbox.gbapal"); -const u16 gBattleInterface_Healthbar_Pal[] = INCBIN_U16("graphics/battle_interface/healthbar.gbapal"); +const u16 gBattleInterface_BallStatusBarPal[] = INCBIN_U16("graphics/battle_interface/healthbox.gbapal"); +const u16 gBattleInterface_BallDisplayPal[] = INCBIN_U16("graphics/battle_interface/healthbar.gbapal"); const u8 gHealthboxElementsGfxTable[][32] = INCBIN_U8("graphics/battle_interface/hpbar.4bpp", "graphics/battle_interface/expbar.4bpp", "graphics/battle_interface/status.4bpp", @@ -1093,7 +1093,7 @@ const u16 gBattleAnimBackgroundImageMuddyWater_Pal[] = INCBIN_U16("graphics/batt const u32 gEnemyMonShadow_Gfx[] = INCBIN_U32("graphics/battle_interface/enemy_mon_shadow.4bpp.smol"); const u32 gEnemyMonShadowsSized_Gfx[] = INCBIN_U32("graphics/battle_interface/enemy_mon_shadows_sized.4bpp.smol"); -const u32 gBattleInterface_PartySummaryBar_Gfx[] = INCBIN_U32("graphics/battle_interface/party_summary_bar.4bpp.smol"); +const u32 gBattleInterface_BallStatusBarGfx[] = INCBIN_U32("graphics/battle_interface/party_summary_bar.4bpp.smol"); const u32 gBattleAnimBgImage_Ghost[] = INCBIN_U32("graphics/battle_anims/backgrounds/ghost.4bpp.smol"); const u16 gBattleAnimBgPalette_Ghost[] = INCBIN_U16("graphics/battle_anims/backgrounds/ghost.gbapal"); diff --git a/src/reshow_battle_screen.c b/src/reshow_battle_screen.c index d349bcd7b..112556b1d 100644 --- a/src/reshow_battle_screen.c +++ b/src/reshow_battle_screen.c @@ -97,6 +97,7 @@ static void CB2_ReshowBattleScreenAfterMenu(void) case 6: if (BattleLoadAllHealthBoxesGfx(gBattleScripting.reshowHelperState)) { + LoadIndicatorSpritesGfx(); gBattleScripting.reshowHelperState = 0; } else diff --git a/src/text.c b/src/text.c index 0d27532d8..cf9309add 100644 --- a/src/text.c +++ b/src/text.c @@ -511,8 +511,10 @@ bool32 AddTextPrinter(struct TextPrinterTemplate *printerTemplate, u8 speed, voi sTempTextPrinter.textSpeed = speed; if (printerTemplate->type == SPRITE_TEXT_PRINTER) - printerTemplate->firstSprite = printerTemplate->spriteId; - + { + sTempTextPrinter.printerTemplate.firstSprite = printerTemplate->spriteId; + sTempTextPrinter.printerTemplate.firstSpriteInRow = printerTemplate->spriteId; + } GenerateFontHalfRowLookupTable(printerTemplate->color); if (speed != TEXT_SKIP_DRAW && speed != 0) diff --git a/src/util.c b/src/util.c index 68fe80f16..2a280fa92 100644 --- a/src/util.c +++ b/src/util.c @@ -281,3 +281,15 @@ void BlendPalettesAt(u16 * palbuff, u16 blend_pal, u32 coefficient, s32 size) } } } + +s32 SubtractClamped(s32 lowestVal, s32 highestVal, s32 currentVal, s32 delta) +{ + s32 newValue = currentVal - delta; + if (newValue > highestVal) + newValue = highestVal; + else if (newValue < lowestVal) + newValue = lowestVal; + + return newValue; +} +