pokeemerald/src/battle_interface.c

2795 lines
93 KiB
C
Raw Normal View History

2017-10-16 18:12:27 +02:00
#include "global.h"
2018-12-09 13:12:02 +01:00
#include "alloc.h"
2017-10-16 18:12:27 +02:00
#include "battle.h"
#include "pokemon.h"
2017-10-19 15:28:41 +02:00
#include "battle_controllers.h"
2017-10-16 18:12:27 +02:00
#include "battle_interface.h"
2018-10-21 09:24:57 +02:00
#include "graphics.h"
2017-10-16 18:12:27 +02:00
#include "sprite.h"
2017-10-18 00:00:46 +02:00
#include "window.h"
#include "string_util.h"
#include "text.h"
2017-10-18 21:42:00 +02:00
#include "sound.h"
2017-12-11 19:27:51 +01:00
#include "constants/songs.h"
2017-10-18 21:42:00 +02:00
#include "decompress.h"
#include "task.h"
#include "util.h"
#include "gpu_regs.h"
#include "battle_message.h"
2017-12-11 19:27:51 +01:00
#include "constants/species.h"
2017-10-18 23:05:14 +02:00
#include "pokedex.h"
#include "palette.h"
#include "international_string_util.h"
#include "safari_zone.h"
2017-10-20 19:24:46 +02:00
#include "battle_anim.h"
#include "constants/battle_anim.h"
2018-01-29 14:36:13 +01:00
#include "constants/rgb.h"
2018-03-01 00:59:52 +01:00
#include "data2.h"
2018-07-29 17:19:57 +02:00
#include "battle_debug.h"
2018-11-03 10:51:51 +01:00
#include "constants/battle_config.h"
2017-10-16 18:12:27 +02:00
2017-10-19 18:25:48 +02:00
enum
{ // 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
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_25,
HEALTHBOX_GFX_26,
HEALTHBOX_GFX_STATUS_SLP_BATTLER0, //status slp
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_28,
HEALTHBOX_GFX_29,
HEALTHBOX_GFX_STATUS_FRZ_BATTLER0, //status frz
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_31,
HEALTHBOX_GFX_32,
HEALTHBOX_GFX_STATUS_BRN_BATTLER0, //status brn
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_34,
HEALTHBOX_GFX_35,
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_66, //status ball [full]
HEALTHBOX_GFX_67, //status ball [empty]
HEALTHBOX_GFX_68, //status ball [fainted]
HEALTHBOX_GFX_69, //status ball [statused]
HEALTHBOX_GFX_70, //status ball [unused extra]
HEALTHBOX_GFX_STATUS_PSN_BATTLER1, //status2 "PSN"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_72,
HEALTHBOX_GFX_73,
HEALTHBOX_GFX_STATUS_PRZ_BATTLER1, //status2 "PRZ"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_75,
HEALTHBOX_GFX_76,
HEALTHBOX_GFX_STATUS_SLP_BATTLER1, //status2 "SLP"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_78,
HEALTHBOX_GFX_79,
HEALTHBOX_GFX_STATUS_FRZ_BATTLER1, //status2 "FRZ"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_81,
HEALTHBOX_GFX_82,
HEALTHBOX_GFX_STATUS_BRN_BATTLER1, //status2 "BRN"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_84,
HEALTHBOX_GFX_85,
HEALTHBOX_GFX_STATUS_PSN_BATTLER2, //status3 "PSN"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_87,
HEALTHBOX_GFX_88,
HEALTHBOX_GFX_STATUS_PRZ_BATTLER2, //status3 "PRZ"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_90,
HEALTHBOX_GFX_91,
HEALTHBOX_GFX_STATUS_SLP_BATTLER2, //status3 "SLP"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_93,
HEALTHBOX_GFX_94,
HEALTHBOX_GFX_STATUS_FRZ_BATTLER2, //status3 "FRZ"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_96,
HEALTHBOX_GFX_97,
HEALTHBOX_GFX_STATUS_BRN_BATTLER2, //status3 "BRN"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_99,
HEALTHBOX_GFX_100,
HEALTHBOX_GFX_STATUS_PSN_BATTLER3, //status4 "PSN"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_102,
HEALTHBOX_GFX_103,
HEALTHBOX_GFX_STATUS_PRZ_BATTLER3, //status4 "PRZ"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_105,
HEALTHBOX_GFX_106,
HEALTHBOX_GFX_STATUS_SLP_BATTLER3, //status4 "SLP"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_108,
HEALTHBOX_GFX_109,
HEALTHBOX_GFX_STATUS_FRZ_BATTLER3, //status4 "FRZ"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_111,
HEALTHBOX_GFX_112,
HEALTHBOX_GFX_STATUS_BRN_BATTLER3, //status4 "BRN"
2017-10-19 18:25:48 +02:00
HEALTHBOX_GFX_114,
HEALTHBOX_GFX_115,
HEALTHBOX_GFX_116, //unknown_D12FEC
HEALTHBOX_GFX_117, //unknown_D1300C
2017-10-19 18:25:48 +02:00
};
2018-06-19 00:43:15 +02:00
extern const u8 *const gNatureNamePointers[];
2017-10-19 15:28:41 +02:00
// strings
2017-10-18 21:42:00 +02:00
extern const u8 gText_Slash[];
2017-10-19 15:28:41 +02:00
extern const u8 gText_HighlightDarkGrey[];
extern const u8 gText_DynColor2[];
extern const u8 gText_DynColor2Male[];
extern const u8 gText_DynColor1Female[];
2017-10-16 18:12:27 +02:00
// this file's functions
2017-10-19 15:28:41 +02:00
static const u8 *GetHealthboxElementGfxPtr(u8 elementId);
2018-11-22 02:10:50 +01:00
static u8* AddTextPrinterAndCreateWindowOnHealthbox(const u8 *str, u32 x, u32 y, u32 bgColor, u32 *windowId);
2017-10-19 15:28:41 +02:00
static void RemoveWindowOnHealthbox(u32 windowId);
static void UpdateHpTextInHealthboxInDoubles(u8 healthboxSpriteId, s16 value, u8 maxOrCurrent);
static void UpdateStatusIconInHealthbox(u8 healthboxSpriteId);
2018-11-22 02:10:50 +01:00
static void TextIntoHealthboxObject(void *dest, u8 *windowTileData, s32 windowWidth);
static void SafariTextIntoHealthboxObject(void *dest, u8 *windowTileData, u32 windowWidth);
static void HpTextIntoHealthboxObject(void *dest, u8 *windowTileData, u32 windowWidth);
2018-06-19 00:43:15 +02:00
static void FillHealthboxObject(void *dest, u32 arg1, u32 arg2);
2017-10-19 15:28:41 +02:00
static void sub_8073E08(u8 taskId);
static void sub_8073F98(u8 taskId);
static void sub_8073E64(u8 taskId);
2018-06-19 00:43:15 +02:00
static void SpriteCB_HealthBoxOther(struct Sprite *sprite);
static void SpriteCB_HealthBar(struct Sprite *sprite);
2017-10-19 15:28:41 +02:00
static void sub_8074158(struct Sprite *sprite);
static void sub_8074090(struct Sprite *sprite);
2017-10-19 18:25:48 +02:00
static void SpriteCB_StatusSummaryBar(struct Sprite *sprite);
static void SpriteCB_StatusSummaryBallsOnBattleStart(struct Sprite *sprite);
static void SpriteCB_StatusSummaryBallsOnSwitchout(struct Sprite *sprite);
2017-10-19 15:28:41 +02:00
2018-09-17 22:40:49 +02:00
static void SpriteCb_MegaTrigger(struct Sprite *sprite);
2018-06-19 00:43:15 +02:00
static u8 GetStatusIconForBattlerId(u8 statusElementId, u8 battlerId);
static s32 CalcNewBarValue(s32 maxValue, s32 currValue, s32 receivedValue, s32 *arg3, u8 arg4, u16 arg5);
2017-10-22 18:43:15 +02:00
static u8 GetScaledExpFraction(s32 currValue, s32 receivedValue, s32 maxValue, u8 scale);
2018-06-19 00:43:15 +02:00
static void MoveBattleBarGraphically(u8 battlerId, u8 whichBar);
static u8 CalcBarFilledPixels(s32 maxValue, s32 oldValue, s32 receivedValue, s32 *currValue, u8 *arg4, u8 scale);
2017-10-16 18:12:27 +02:00
2018-09-29 12:47:35 +02:00
static void SpriteCb_AbilityPopUp(struct Sprite *sprite);
static void Task_FreeAbilityPopUpGfx(u8 taskId);
2017-10-16 18:12:27 +02:00
// const rom data
2017-10-20 19:24:46 +02:00
static const struct OamData sUnknown_0832C138 =
2017-10-16 18:12:27 +02:00
{
.y = 0,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 0,
.shape = 1,
.x = 0,
.matrixNum = 0,
.size = 3,
.tileNum = 0,
.priority = 1,
.paletteNum = 0,
.affineParam = 0,
};
2017-10-19 18:25:48 +02:00
static const struct SpriteTemplate sHealthboxPlayerSpriteTemplates[2] =
2017-10-16 18:12:27 +02:00
{
{
2017-10-19 18:25:48 +02:00
.tileTag = TAG_HEALTHBOX_PLAYER1_TILE,
.paletteTag = TAG_HEALTHBOX_PAL,
2017-10-20 19:24:46 +02:00
.oam = &sUnknown_0832C138,
2017-10-16 18:12:27 +02:00
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
},
{
2017-10-19 18:25:48 +02:00
.tileTag = TAG_HEALTHBOX_PLAYER2_TILE,
.paletteTag = TAG_HEALTHBOX_PAL,
2017-10-20 19:24:46 +02:00
.oam = &sUnknown_0832C138,
2017-10-16 18:12:27 +02:00
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
}
};
2017-10-19 18:25:48 +02:00
static const struct SpriteTemplate sHealthboxOpponentSpriteTemplates[2] =
2017-10-16 18:12:27 +02:00
{
{
2017-10-19 18:25:48 +02:00
.tileTag = TAG_HEALTHBOX_OPPONENT1_TILE,
.paletteTag = TAG_HEALTHBOX_PAL,
2017-10-20 19:24:46 +02:00
.oam = &sUnknown_0832C138,
2017-10-16 18:12:27 +02:00
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
},
{
2017-10-19 18:25:48 +02:00
.tileTag = TAG_HEALTHBOX_OPPONENT2_TILE,
.paletteTag = TAG_HEALTHBOX_PAL,
2017-10-20 19:24:46 +02:00
.oam = &sUnknown_0832C138,
2017-10-16 18:12:27 +02:00
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
}
};
2017-10-19 18:25:48 +02:00
static const struct SpriteTemplate sHealthboxSafariSpriteTemplate =
2017-10-16 18:12:27 +02:00
{
2017-10-19 18:25:48 +02:00
.tileTag = TAG_HEALTHBOX_SAFARI_TILE,
.paletteTag = TAG_HEALTHBOX_PAL,
2017-10-20 19:24:46 +02:00
.oam = &sUnknown_0832C138,
2017-10-16 18:12:27 +02:00
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
};
2018-06-19 00:43:15 +02:00
static const struct OamData sOamData_Healthbar =
2017-10-16 18:12:27 +02:00
{
.y = 0,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 0,
.shape = 1,
.x = 0,
.matrixNum = 0,
.size = 1,
.tileNum = 0,
.priority = 1,
.paletteNum = 0,
.affineParam = 0,
};
2018-06-19 00:43:15 +02:00
static const struct SpriteTemplate sHealthbarSpriteTemplates[MAX_BATTLERS_COUNT] =
2017-10-16 18:12:27 +02:00
{
{
2018-06-19 00:43:15 +02:00
.tileTag = TAG_HEALTHBAR_PLAYER1_TILE,
.paletteTag = TAG_HEALTHBAR_PAL,
.oam = &sOamData_Healthbar,
2017-10-16 18:12:27 +02:00
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2018-06-19 00:43:15 +02:00
.callback = SpriteCB_HealthBar
2017-10-16 18:12:27 +02:00
},
{
2018-06-19 00:43:15 +02:00
.tileTag = TAG_HEALTHBAR_OPPONENT1_TILE,
.paletteTag = TAG_HEALTHBAR_PAL,
.oam = &sOamData_Healthbar,
2017-10-16 18:12:27 +02:00
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2018-06-19 00:43:15 +02:00
.callback = SpriteCB_HealthBar
2017-10-16 18:12:27 +02:00
},
{
2018-06-19 00:43:15 +02:00
.tileTag = TAG_HEALTHBAR_PLAYER2_TILE,
.paletteTag = TAG_HEALTHBAR_PAL,
.oam = &sOamData_Healthbar,
2017-10-16 18:12:27 +02:00
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2018-06-19 00:43:15 +02:00
.callback = SpriteCB_HealthBar
2017-10-16 18:12:27 +02:00
},
{
2018-06-19 00:43:15 +02:00
.tileTag = TAG_HEALTHBAR_OPPONENT2_TILE,
.paletteTag = TAG_HEALTHBAR_PAL,
.oam = &sOamData_Healthbar,
2017-10-16 18:12:27 +02:00
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2018-06-19 00:43:15 +02:00
.callback = SpriteCB_HealthBar
2017-10-16 18:12:27 +02:00
}
};
2017-10-19 18:25:48 +02:00
static const struct Subsprite sUnknown_0832C258[] =
2017-10-19 15:28:41 +02:00
{
{240, 0, 1, 1, 0, 1},
{16, 0, 1, 1, 4, 1}
};
2017-10-19 18:25:48 +02:00
static const struct Subsprite sUnknown_0832C260[] =
2017-10-19 15:28:41 +02:00
{
{240, 0, 1, 1, 0, 1},
{16, 0, 1, 1, 4, 1},
{224, 0, 0, 0, 8, 1}
};
2017-10-19 18:25:48 +02:00
static const struct SubspriteTable sUnknown_0832C28C[] =
2017-10-19 15:28:41 +02:00
{
2017-10-19 18:25:48 +02:00
{ARRAY_COUNT(sUnknown_0832C258), sUnknown_0832C258},
{ARRAY_COUNT(sUnknown_0832C260), sUnknown_0832C260}
2017-10-19 15:28:41 +02:00
};
2017-10-19 18:25:48 +02:00
static const struct Subsprite sStatusSummaryBar_Subsprites_0[] =
2017-10-19 15:28:41 +02:00
{
{160, 0, 1, 1, 0, 1},
{192, 0, 1, 1, 4, 1},
{224, 0, 1, 1, 8, 1},
{0, 0, 1, 1, 12, 1}
};
2017-10-20 19:24:46 +02:00
static const struct Subsprite sUnknown_0832C2AC[] =
2017-10-19 15:28:41 +02:00
{
{160, 0, 1, 1, 0, 1},
{192, 0, 1, 1, 4, 1},
{224, 0, 1, 1, 8, 1},
{0, 0, 1, 1, 8, 1},
{32, 0, 1, 1, 8, 1},
{64, 0, 1, 1, 12, 1}
};
2017-10-19 18:25:48 +02:00
static const struct SubspriteTable sStatusSummaryBar_SubspriteTable[] =
2017-10-19 15:28:41 +02:00
{
2017-10-19 18:25:48 +02:00
{ARRAY_COUNT(sStatusSummaryBar_Subsprites_0), sStatusSummaryBar_Subsprites_0}
2017-10-19 15:28:41 +02:00
};
2017-10-20 19:24:46 +02:00
static const struct SubspriteTable sUnknown_0832C2CC[] =
2017-10-19 15:28:41 +02:00
{
2017-10-20 19:24:46 +02:00
{ARRAY_COUNT(sUnknown_0832C2AC), sUnknown_0832C2AC}
2017-10-19 15:28:41 +02:00
};
2017-10-19 18:25:48 +02:00
static const struct CompressedSpriteSheet sStatusSummaryBarSpriteSheet =
2017-10-19 15:28:41 +02:00
{
2017-10-19 18:25:48 +02:00
gBattleInterface_BallStatusBarGfx, 0x200, TAG_STATUS_SUMMARY_BAR_TILE
2017-10-19 15:28:41 +02:00
};
2017-10-19 18:25:48 +02:00
static const struct SpritePalette sStatusSummaryBarSpritePal =
2017-10-19 15:28:41 +02:00
{
2017-10-19 18:25:48 +02:00
gBattleInterface_BallStatusBarPal, TAG_STATUS_SUMMARY_BAR_PAL
2017-10-19 15:28:41 +02:00
};
2017-10-19 18:25:48 +02:00
static const struct SpritePalette sStatusSummaryBallsSpritePal =
2017-10-19 15:28:41 +02:00
{
2017-10-19 18:25:48 +02:00
gBattleInterface_BallDisplayPal, TAG_STATUS_SUMMARY_BALLS_PAL
2017-10-19 15:28:41 +02:00
};
2017-10-19 18:25:48 +02:00
static const struct SpriteSheet sStatusSummaryBallsSpriteSheet =
2017-10-19 15:28:41 +02:00
{
2017-10-19 18:25:48 +02:00
gBattleInterface_BallDisplayGfx, 0x80, TAG_STATUS_SUMMARY_BALLS_TILE
2017-10-19 15:28:41 +02:00
};
2017-10-20 19:24:46 +02:00
static const struct OamData sOamData_StatusSummaryBalls =
2017-10-19 15:28:41 +02:00
{
.y = 0,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 0,
.shape = 0,
.x = 0,
.matrixNum = 0,
.size = 0,
.tileNum = 0,
.priority = 1,
.paletteNum = 0,
.affineParam = 0,
};
2017-10-19 18:25:48 +02:00
static const struct SpriteTemplate sStatusSummaryBarSpriteTemplates[2] =
2017-10-19 15:28:41 +02:00
{
{
2017-10-19 18:25:48 +02:00
.tileTag = TAG_STATUS_SUMMARY_BAR_TILE,
.paletteTag = TAG_STATUS_SUMMARY_BAR_PAL,
2017-10-20 19:24:46 +02:00
.oam = &sUnknown_0832C138,
2017-10-19 15:28:41 +02:00
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2017-10-19 18:25:48 +02:00
.callback = SpriteCB_StatusSummaryBar
2017-10-19 15:28:41 +02:00
},
{
2017-10-19 18:25:48 +02:00
.tileTag = TAG_STATUS_SUMMARY_BAR_TILE,
.paletteTag = TAG_STATUS_SUMMARY_BAR_PAL,
2017-10-20 19:24:46 +02:00
.oam = &sUnknown_0832C138,
2017-10-19 15:28:41 +02:00
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2017-10-19 18:25:48 +02:00
.callback = SpriteCB_StatusSummaryBar
2017-10-19 15:28:41 +02:00
}
};
2017-10-19 18:25:48 +02:00
static const struct SpriteTemplate sStatusSummaryBallsSpriteTemplates[2] =
2017-10-19 15:28:41 +02:00
{
{
2017-10-19 18:25:48 +02:00
.tileTag = TAG_STATUS_SUMMARY_BALLS_TILE,
.paletteTag = TAG_STATUS_SUMMARY_BALLS_PAL,
2017-10-20 19:24:46 +02:00
.oam = &sOamData_StatusSummaryBalls,
2017-10-19 15:28:41 +02:00
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2017-10-19 18:25:48 +02:00
.callback = SpriteCB_StatusSummaryBallsOnBattleStart
2017-10-19 15:28:41 +02:00
},
{
2017-10-19 18:25:48 +02:00
.tileTag = TAG_STATUS_SUMMARY_BALLS_TILE,
.paletteTag = TAG_STATUS_SUMMARY_BALLS_PAL,
2017-10-20 19:24:46 +02:00
.oam = &sOamData_StatusSummaryBalls,
2017-10-19 15:28:41 +02:00
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2017-10-19 18:25:48 +02:00
.callback = SpriteCB_StatusSummaryBallsOnBattleStart
2017-10-19 15:28:41 +02:00
}
};
// possibly text
2017-10-20 19:24:46 +02:00
static const u8 sUnknown_0832C3C4[] =
2017-10-19 15:28:41 +02:00
{
0xfc, 0x01, 0x01, 0xfc, 0x02, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
// possibly text
2017-10-20 19:24:46 +02:00
static const u8 sUnknown_0832C3D8[] =
2017-10-19 15:28:41 +02:00
{
0xfc, 0x01, 0x01, 0xfc, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
enum
{
PAL_STATUS_PSN,
PAL_STATUS_PAR,
PAL_STATUS_SLP,
PAL_STATUS_FRZ,
PAL_STATUS_BRN
};
2018-01-29 14:36:13 +01:00
static const u16 sStatusIconColors[] =
2017-10-19 15:28:41 +02:00
{
[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),
2017-10-19 15:28:41 +02:00
};
static const struct WindowTemplate sHealthboxWindowTemplate = {0, 0, 0, 8, 2, 0, 0}; // width = 8, height = 2
2018-09-17 22:40:49 +02:00
static const u8 sMegaTriggerGfx[] = INCBIN_U8("graphics/battle_interface/mega_trigger.4bpp");
2018-09-20 20:59:00 +02:00
static const u16 sMegaTriggerPal[] = INCBIN_U16("graphics/battle_interface/mega_trigger.gbapal");
2018-09-17 22:40:49 +02:00
static const struct SpriteSheet sSpriteSheet_MegaTrigger =
{
sMegaTriggerGfx, sizeof(sMegaTriggerGfx), TAG_MEGA_TRIGGER_TILE
};
2018-09-20 20:59:00 +02:00
static const struct SpritePalette sSpritePalette_MegaTrigger =
2018-09-17 22:40:49 +02:00
{
2018-09-20 20:59:00 +02:00
sMegaTriggerPal, TAG_MEGA_TRIGGER_PAL
2018-09-17 22:40:49 +02:00
};
static const struct OamData sOamData_MegaTrigger =
{
.y = 0,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 0,
.shape = ST_OAM_SQUARE,
.x = 0,
.matrixNum = 0,
.size = 2,
.tileNum = 0,
2018-09-20 20:59:00 +02:00
.priority = 1,
2018-09-17 22:40:49 +02:00
.paletteNum = 0,
.affineParam = 0,
};
2018-09-20 20:59:00 +02:00
static const union AnimCmd sSpriteAnim_MegaTriggerOff[] =
{
ANIMCMD_FRAME(0, 0),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_MegaTriggerOn[] =
{
ANIMCMD_FRAME(16, 0),
ANIMCMD_END
};
static const union AnimCmd *const sSpriteAnimTable_MegaTrigger[] =
{
sSpriteAnim_MegaTriggerOff,
sSpriteAnim_MegaTriggerOn,
};
2018-09-17 22:40:49 +02:00
static const struct SpriteTemplate sSpriteTemplate_MegaTrigger =
{
.tileTag = TAG_MEGA_TRIGGER_TILE,
2018-09-20 20:59:00 +02:00
.paletteTag = TAG_MEGA_TRIGGER_PAL,
2018-09-17 22:40:49 +02:00
.oam = &sOamData_MegaTrigger,
2018-09-20 20:59:00 +02:00
.anims = sSpriteAnimTable_MegaTrigger,
2018-09-17 22:40:49 +02:00
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCb_MegaTrigger
};
2017-10-19 15:28:41 +02:00
// code
2018-06-19 00:43:15 +02:00
// 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.
2017-10-19 18:25:48 +02:00
2018-06-19 00:43:15 +02:00
// 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]
u8 CreateBattlerHealthboxSprites(u8 battlerId)
2017-10-16 18:12:27 +02:00
{
s16 data6 = 0;
2018-06-19 00:43:15 +02:00
u8 healthboxLeftSpriteId, healthboxRightSpriteId;
u8 healthbarSpriteId;
struct Sprite *healthBarSpritePtr;
2017-10-16 18:12:27 +02:00
if (!IsDoubleBattle())
{
2018-06-19 00:43:15 +02:00
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
2017-10-16 18:12:27 +02:00
{
2018-06-19 00:43:15 +02:00
healthboxLeftSpriteId = CreateSprite(&sHealthboxPlayerSpriteTemplates[0], 240, 160, 1);
healthboxRightSpriteId = CreateSpriteAtEnd(&sHealthboxPlayerSpriteTemplates[0], 240, 160, 1);
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
gSprites[healthboxLeftSpriteId].oam.shape = 0;
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
gSprites[healthboxRightSpriteId].oam.shape = 0;
gSprites[healthboxRightSpriteId].oam.tileNum += 64;
2017-10-16 18:12:27 +02:00
}
else
{
2018-06-19 00:43:15 +02:00
healthboxLeftSpriteId = CreateSprite(&sHealthboxOpponentSpriteTemplates[0], 240, 160, 1);
healthboxRightSpriteId = CreateSpriteAtEnd(&sHealthboxOpponentSpriteTemplates[0], 240, 160, 1);
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
gSprites[healthboxRightSpriteId].oam.tileNum += 32;
2017-10-16 18:12:27 +02:00
data6 = 2;
}
2018-06-19 00:43:15 +02:00
gSprites[healthboxLeftSpriteId].oam.affineParam = healthboxRightSpriteId;
gSprites[healthboxRightSpriteId].hOther_HealthBoxSpriteId = healthboxLeftSpriteId;
gSprites[healthboxRightSpriteId].callback = SpriteCB_HealthBoxOther;
2017-10-16 18:12:27 +02:00
}
else
{
2018-06-19 00:43:15 +02:00
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
2017-10-16 18:12:27 +02:00
{
2018-06-19 00:43:15 +02:00
healthboxLeftSpriteId = CreateSprite(&sHealthboxPlayerSpriteTemplates[GetBattlerPosition(battlerId) / 2], 240, 160, 1);
healthboxRightSpriteId = CreateSpriteAtEnd(&sHealthboxPlayerSpriteTemplates[GetBattlerPosition(battlerId) / 2], 240, 160, 1);
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
gSprites[healthboxLeftSpriteId].oam.affineParam = healthboxRightSpriteId;
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
gSprites[healthboxRightSpriteId].hOther_HealthBoxSpriteId = healthboxLeftSpriteId;
gSprites[healthboxRightSpriteId].oam.tileNum += 32;
gSprites[healthboxRightSpriteId].callback = SpriteCB_HealthBoxOther;
2017-10-16 18:12:27 +02:00
data6 = 1;
}
else
{
2018-06-19 00:43:15 +02:00
healthboxLeftSpriteId = CreateSprite(&sHealthboxOpponentSpriteTemplates[GetBattlerPosition(battlerId) / 2], 240, 160, 1);
healthboxRightSpriteId = CreateSpriteAtEnd(&sHealthboxOpponentSpriteTemplates[GetBattlerPosition(battlerId) / 2], 240, 160, 1);
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
gSprites[healthboxLeftSpriteId].oam.affineParam = healthboxRightSpriteId;
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
gSprites[healthboxRightSpriteId].hOther_HealthBoxSpriteId = healthboxLeftSpriteId;
gSprites[healthboxRightSpriteId].oam.tileNum += 32;
gSprites[healthboxRightSpriteId].callback = SpriteCB_HealthBoxOther;
2017-10-16 18:12:27 +02:00
data6 = 2;
}
}
2018-06-19 00:43:15 +02:00
healthbarSpriteId = CreateSpriteAtEnd(&sHealthbarSpriteTemplates[gBattlerPositions[battlerId]], 140, 60, 0);
healthBarSpritePtr = &gSprites[healthbarSpriteId];
SetSubspriteTables(healthBarSpritePtr, &sUnknown_0832C28C[GetBattlerSide(battlerId)]);
healthBarSpritePtr->subspriteMode = 2;
healthBarSpritePtr->oam.priority = 1;
2017-10-16 18:12:27 +02:00
2018-11-22 02:10:50 +01:00
CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_1), (void*)(OBJ_VRAM0 + healthBarSpritePtr->oam.tileNum * TILE_SIZE_4BPP), 64);
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
gSprites[healthboxLeftSpriteId].hMain_HealthBarSpriteId = healthbarSpriteId;
gSprites[healthboxLeftSpriteId].hMain_Battler = battlerId;
gSprites[healthboxLeftSpriteId].invisible = TRUE;
2017-10-16 18:12:27 +02:00
gSprites[healthboxRightSpriteId].invisible = TRUE;
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
healthBarSpritePtr->hBar_HealthBoxSpriteId = healthboxLeftSpriteId;
healthBarSpritePtr->hBar_Data6 = data6;
healthBarSpritePtr->invisible = TRUE;
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
return healthboxLeftSpriteId;
2017-10-16 18:12:27 +02:00
}
u8 CreateSafariPlayerHealthboxSprites(void)
{
2018-06-19 00:43:15 +02:00
u8 healthboxLeftSpriteId, healthboxRightSpriteId;
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
healthboxLeftSpriteId = CreateSprite(&sHealthboxSafariSpriteTemplate, 240, 160, 1);
healthboxRightSpriteId = CreateSpriteAtEnd(&sHealthboxSafariSpriteTemplate, 240, 160, 1);
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
gSprites[healthboxLeftSpriteId].oam.shape = 0;
gSprites[healthboxRightSpriteId].oam.shape = 0;
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
gSprites[healthboxRightSpriteId].oam.tileNum += 64;
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
gSprites[healthboxLeftSpriteId].oam.affineParam = healthboxRightSpriteId;
gSprites[healthboxRightSpriteId].hOther_HealthBoxSpriteId = healthboxLeftSpriteId;
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
gSprites[healthboxRightSpriteId].callback = SpriteCB_HealthBoxOther;
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
return healthboxLeftSpriteId;
2017-10-16 18:12:27 +02:00
}
2017-10-19 15:28:41 +02:00
static const u8 *GetHealthboxElementGfxPtr(u8 elementId)
2017-10-16 18:12:27 +02:00
{
return gHealthboxElementsGfxTable[elementId];
}
2018-06-19 00:43:15 +02:00
// Syncs the position of healthbar accordingly with the healthbox.
static void SpriteCB_HealthBar(struct Sprite *sprite)
2017-10-16 18:12:27 +02:00
{
2018-06-19 00:43:15 +02:00
u8 healthboxSpriteId = sprite->hBar_HealthBoxSpriteId;
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
switch (sprite->hBar_Data6)
2017-10-16 18:12:27 +02:00
{
case 0:
2018-06-19 00:43:15 +02:00
sprite->pos1.x = gSprites[healthboxSpriteId].pos1.x + 16;
sprite->pos1.y = gSprites[healthboxSpriteId].pos1.y;
2017-10-16 18:12:27 +02:00
break;
case 1:
2018-06-19 00:43:15 +02:00
sprite->pos1.x = gSprites[healthboxSpriteId].pos1.x + 16;
sprite->pos1.y = gSprites[healthboxSpriteId].pos1.y;
2017-10-16 18:12:27 +02:00
break;
case 2:
default:
2018-06-19 00:43:15 +02:00
sprite->pos1.x = gSprites[healthboxSpriteId].pos1.x + 8;
sprite->pos1.y = gSprites[healthboxSpriteId].pos1.y;
2017-10-16 18:12:27 +02:00
break;
}
2018-06-19 00:43:15 +02:00
sprite->pos2.x = gSprites[healthboxSpriteId].pos2.x;
sprite->pos2.y = gSprites[healthboxSpriteId].pos2.y;
2017-10-16 18:12:27 +02:00
}
2018-06-19 00:43:15 +02:00
static void SpriteCB_HealthBoxOther(struct Sprite *sprite)
2017-10-16 18:12:27 +02:00
{
2018-06-19 00:43:15 +02:00
u8 healthboxMainSpriteId = sprite->hOther_HealthBoxSpriteId;
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
sprite->pos1.x = gSprites[healthboxMainSpriteId].pos1.x + 64;
sprite->pos1.y = gSprites[healthboxMainSpriteId].pos1.y;
2017-10-16 18:12:27 +02:00
2018-06-19 00:43:15 +02:00
sprite->pos2.x = gSprites[healthboxMainSpriteId].pos2.x;
sprite->pos2.y = gSprites[healthboxMainSpriteId].pos2.y;
2017-10-16 18:12:27 +02:00
}
2018-06-19 00:43:15 +02:00
void SetBattleBarStruct(u8 battlerId, u8 healthboxSpriteId, s32 maxVal, s32 oldVal, s32 receivedValue)
2017-10-16 18:12:27 +02:00
{
2018-03-01 00:59:52 +01:00
gBattleSpritesDataPtr->battleBars[battlerId].healthboxSpriteId = healthboxSpriteId;
gBattleSpritesDataPtr->battleBars[battlerId].maxValue = maxVal;
2018-06-19 00:43:15 +02:00
gBattleSpritesDataPtr->battleBars[battlerId].oldValue = oldVal;
2018-03-01 00:59:52 +01:00
gBattleSpritesDataPtr->battleBars[battlerId].receivedValue = receivedValue;
2018-06-19 00:43:15 +02:00
gBattleSpritesDataPtr->battleBars[battlerId].currValue = -32768;
2017-10-16 18:12:27 +02:00
}
2017-10-18 00:00:46 +02:00
void SetHealthboxSpriteInvisible(u8 healthboxSpriteId)
{
gSprites[healthboxSpriteId].invisible = TRUE;
gSprites[gSprites[healthboxSpriteId].hMain_HealthBarSpriteId].invisible = TRUE;
gSprites[gSprites[healthboxSpriteId].oam.affineParam].invisible = TRUE;
2017-10-18 00:00:46 +02:00
}
void SetHealthboxSpriteVisible(u8 healthboxSpriteId)
{
gSprites[healthboxSpriteId].invisible = FALSE;
gSprites[gSprites[healthboxSpriteId].hMain_HealthBarSpriteId].invisible = FALSE;
gSprites[gSprites[healthboxSpriteId].oam.affineParam].invisible = FALSE;
2017-10-18 00:00:46 +02:00
}
static void UpdateSpritePos(u8 spriteId, s16 x, s16 y)
{
gSprites[spriteId].pos1.x = x;
gSprites[spriteId].pos1.y = y;
}
void DestoryHealthboxSprite(u8 healthboxSpriteId)
{
DestroySprite(&gSprites[gSprites[healthboxSpriteId].oam.affineParam]);
2018-06-19 00:43:15 +02:00
DestroySprite(&gSprites[gSprites[healthboxSpriteId].hMain_HealthBarSpriteId]);
2017-10-18 00:00:46 +02:00
DestroySprite(&gSprites[healthboxSpriteId]);
}
2018-06-19 00:43:15 +02:00
void DummyBattleInterfaceFunc(u8 healthboxSpriteId, bool8 isDoubleBattleBattlerOnly)
2017-10-18 00:00:46 +02:00
{
}
void UpdateOamPriorityInAllHealthboxes(u8 priority)
{
s32 i;
2018-02-06 02:46:59 +01:00
for (i = 0; i < gBattlersCount; i++)
2017-10-18 00:00:46 +02:00
{
2018-06-19 00:43:15 +02:00
u8 healthboxLeftSpriteId = gHealthboxSpriteIds[i];
u8 healthboxRightSpriteId = gSprites[gHealthboxSpriteIds[i]].oam.affineParam;
u8 healthbarSpriteId = gSprites[gHealthboxSpriteIds[i]].hMain_HealthBarSpriteId;
2017-10-18 00:00:46 +02:00
2018-06-19 00:43:15 +02:00
gSprites[healthboxLeftSpriteId].oam.priority = priority;
gSprites[healthboxRightSpriteId].oam.priority = priority;
gSprites[healthbarSpriteId].oam.priority = priority;
2017-10-18 00:00:46 +02:00
}
}
2018-02-06 23:09:39 +01:00
void InitBattlerHealthboxCoords(u8 battler)
2017-10-18 00:00:46 +02:00
{
s16 x = 0, y = 0;
if (!IsDoubleBattle())
{
2018-02-06 23:09:39 +01:00
if (GetBattlerSide(battler) != B_SIDE_PLAYER)
2017-10-18 00:00:46 +02:00
x = 44, y = 30;
else
x = 158, y = 88;
}
else
{
2018-02-06 23:09:39 +01:00
switch (GetBattlerPosition(battler))
2017-10-18 00:00:46 +02:00
{
2018-01-16 21:01:31 +01:00
case B_POSITION_PLAYER_LEFT:
2017-10-18 00:00:46 +02:00
x = 159, y = 76;
break;
2018-01-16 21:01:31 +01:00
case B_POSITION_PLAYER_RIGHT:
2017-10-18 00:00:46 +02:00
x = 171, y = 101;
break;
2018-01-16 21:01:31 +01:00
case B_POSITION_OPPONENT_LEFT:
2017-10-18 00:00:46 +02:00
x = 44, y = 19;
break;
2018-01-16 21:01:31 +01:00
case B_POSITION_OPPONENT_RIGHT:
2017-10-18 00:00:46 +02:00
x = 32, y = 44;
break;
}
}
2018-02-06 23:09:39 +01:00
UpdateSpritePos(gHealthboxSpriteIds[battler], x, y);
2017-10-18 00:00:46 +02:00
}
2017-10-19 15:28:41 +02:00
static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl)
2017-10-18 00:00:46 +02:00
{
2017-10-19 15:28:41 +02:00
u32 windowId, spriteTileNum;
u8 *windowTileData;
2017-10-18 00:00:46 +02:00
u8 text[16];
u32 xPos, var1;
void *objVram;
text[0] = 0xF9;
text[1] = 5;
xPos = (u32) ConvertIntToDecimalStringN(text + 2, lvl, STR_CONV_MODE_LEFT_ALIGN, 3);
// Alright, that part was unmatchable. It's basically doing:
// xPos = 5 * (3 - (u32)(&text[2]));
xPos--;
xPos--;
xPos -= ((u32)(text));
var1 = (3 - xPos);
xPos = 4 * var1;
xPos += var1;
windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, xPos, 3, 2, &windowId);
2018-11-22 02:10:50 +01:00
spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * TILE_SIZE_4BPP;
2017-10-18 00:00:46 +02:00
2018-06-19 00:43:15 +02:00
if (GetBattlerSide(gSprites[healthboxSpriteId].hMain_Battler) == B_SIDE_PLAYER)
2017-10-18 00:00:46 +02:00
{
objVram = (void*)(OBJ_VRAM0);
if (!IsDoubleBattle())
objVram += spriteTileNum + 0x820;
else
objVram += spriteTileNum + 0x420;
}
else
{
objVram = (void*)(OBJ_VRAM0);
objVram += spriteTileNum + 0x400;
}
2018-06-19 00:43:15 +02:00
TextIntoHealthboxObject(objVram, windowTileData, 3);
2017-10-18 23:05:14 +02:00
RemoveWindowOnHealthbox(windowId);
2017-10-18 00:00:46 +02:00
}
void UpdateHpTextInHealthbox(u8 healthboxSpriteId, s16 value, u8 maxOrCurrent)
{
2017-10-19 15:28:41 +02:00
u32 windowId, spriteTileNum;
u8 *windowTileData;
2017-10-18 00:00:46 +02:00
u8 text[32];
void *objVram;
2018-06-19 00:43:15 +02:00
if (GetBattlerSide(gSprites[healthboxSpriteId].hMain_Battler) == B_SIDE_PLAYER && !IsDoubleBattle())
2017-10-18 00:00:46 +02:00
{
2018-11-22 02:10:50 +01:00
spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * TILE_SIZE_4BPP;
2017-10-19 18:25:48 +02:00
if (maxOrCurrent != HP_CURRENT) // singles, max
2017-10-18 00:00:46 +02:00
{
ConvertIntToDecimalStringN(text, value, STR_CONV_MODE_RIGHT_ALIGN, 3);
windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, 0, 5, 2, &windowId);
objVram = (void*)(OBJ_VRAM0);
objVram += spriteTileNum + 0xB40;
2018-06-19 00:43:15 +02:00
HpTextIntoHealthboxObject(objVram, windowTileData, 2);
2017-10-18 23:05:14 +02:00
RemoveWindowOnHealthbox(windowId);
2017-10-18 00:00:46 +02:00
}
else // singles, current
{
ConvertIntToDecimalStringN(text, value, STR_CONV_MODE_RIGHT_ALIGN, 3);
text[3] = CHAR_SLASH;
text[4] = EOS;
windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, 4, 5, 2, &windowId);
objVram = (void*)(OBJ_VRAM0);
objVram += spriteTileNum + 0x3E0;
2018-06-19 00:43:15 +02:00
HpTextIntoHealthboxObject(objVram, windowTileData, 1);
2017-10-18 00:00:46 +02:00
objVram = (void*)(OBJ_VRAM0);
objVram += spriteTileNum + 0xB00;
2018-06-19 00:43:15 +02:00
HpTextIntoHealthboxObject(objVram, windowTileData + 0x20, 2);
2017-10-18 23:05:14 +02:00
RemoveWindowOnHealthbox(windowId);
2017-10-18 00:00:46 +02:00
}
}
else
{
2018-02-06 23:09:39 +01:00
u8 battler;
2017-10-18 00:00:46 +02:00
2017-10-20 19:24:46 +02:00
memcpy(text, sUnknown_0832C3C4, sizeof(sUnknown_0832C3C4));
2018-06-19 00:43:15 +02:00
battler = gSprites[healthboxSpriteId].hMain_Battler;
2018-07-29 17:19:57 +02:00
if (IsDoubleBattle() == TRUE)
2017-10-18 00:00:46 +02:00
{
UpdateHpTextInHealthboxInDoubles(healthboxSpriteId, value, maxOrCurrent);
}
2018-08-01 22:01:37 +02:00
else if (gBattleSpritesDataPtr->battlerData[battler].hpNumbersNoBars) // don't print text if only bars are visible
2017-10-18 00:00:46 +02:00
{
u32 var;
u8 i;
2018-02-06 02:46:59 +01:00
if (GetBattlerSide(gSprites[healthboxSpriteId].data[6]) == B_SIDE_PLAYER)
2017-10-18 00:00:46 +02:00
{
2017-10-19 18:25:48 +02:00
if (maxOrCurrent == HP_CURRENT)
2017-10-18 00:00:46 +02:00
var = 29;
else
var = 89;
}
else
{
2017-10-19 18:25:48 +02:00
if (maxOrCurrent == HP_CURRENT)
2018-07-29 17:19:57 +02:00
var = 21;
2017-10-18 00:00:46 +02:00
else
2018-07-29 17:19:57 +02:00
var = 49;
2017-10-18 00:00:46 +02:00
}
2018-07-29 17:19:57 +02:00
ConvertIntToDecimalStringN(text + 6, value, STR_CONV_MODE_LEADING_ZEROS, 3);
2017-11-04 16:25:19 +01:00
RenderTextFont9(gMonSpritesGfxPtr->barFontGfx, 9, text);
2017-10-18 00:00:46 +02:00
for (i = 0; i < 3; i++)
{
2017-11-04 16:25:19 +01:00
CpuCopy32(&gMonSpritesGfxPtr->barFontGfx[i * 64 + 32],
2018-11-22 02:10:50 +01:00
(void*)((OBJ_VRAM0) + TILE_SIZE_4BPP * (gSprites[healthboxSpriteId].oam.tileNum + var + i)),
2017-10-18 00:00:46 +02:00
0x20);
}
}
}
}
2017-10-19 15:28:41 +02:00
static void UpdateHpTextInHealthboxInDoubles(u8 healthboxSpriteId, s16 value, u8 maxOrCurrent)
2017-10-18 00:00:46 +02:00
{
2017-10-19 15:28:41 +02:00
u32 windowId, spriteTileNum;
u8 *windowTileData;
2017-10-18 00:00:46 +02:00
u8 text[32];
void *objVram;
2018-06-19 00:43:15 +02:00
if (GetBattlerSide(gSprites[healthboxSpriteId].hMain_Battler) == B_SIDE_PLAYER)
2017-10-18 00:00:46 +02:00
{
2018-02-06 23:09:39 +01:00
if (gBattleSpritesDataPtr->battlerData[gSprites[healthboxSpriteId].data[6]].hpNumbersNoBars) // don't print text if only bars are visible
2017-10-18 00:00:46 +02:00
{
2018-11-22 02:10:50 +01:00
spriteTileNum = gSprites[gSprites[healthboxSpriteId].data[5]].oam.tileNum * TILE_SIZE_4BPP;
2017-10-18 00:00:46 +02:00
objVram = (void*)(OBJ_VRAM0) + spriteTileNum;
2017-10-19 18:25:48 +02:00
if (maxOrCurrent != HP_CURRENT) // doubles, max hp
2017-10-18 00:00:46 +02:00
{
ConvertIntToDecimalStringN(text, value, STR_CONV_MODE_RIGHT_ALIGN, 3);
windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, 0, 5, 0, &windowId);
2018-06-19 00:43:15 +02:00
HpTextIntoHealthboxObject((void*)(OBJ_VRAM0) + spriteTileNum + 0xC0, windowTileData, 2);
2017-10-18 23:05:14 +02:00
RemoveWindowOnHealthbox(windowId);
2017-10-19 18:25:48 +02:00
CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_116),
2018-11-22 02:10:50 +01:00
(void*)(OBJ_VRAM0 + 0x680) + (gSprites[healthboxSpriteId].oam.tileNum * TILE_SIZE_4BPP),
2017-10-18 00:00:46 +02:00
0x20);
}
else
{
ConvertIntToDecimalStringN(text, value, STR_CONV_MODE_RIGHT_ALIGN, 3);
text[3] = CHAR_SLASH;
text[4] = EOS;
windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, 4, 5, 0, &windowId);
2018-06-19 00:43:15 +02:00
FillHealthboxObject(objVram, 0, 3); // Erases HP bar leftover.
HpTextIntoHealthboxObject((void*)(OBJ_VRAM0 + 0x60) + spriteTileNum, windowTileData, 3);
2017-10-18 23:05:14 +02:00
RemoveWindowOnHealthbox(windowId);
2017-10-18 00:00:46 +02:00
}
}
}
else
{
2018-03-01 00:59:52 +01:00
u8 battlerId;
2017-10-18 00:00:46 +02:00
2017-10-20 19:24:46 +02:00
memcpy(text, sUnknown_0832C3D8, sizeof(sUnknown_0832C3D8));
2018-06-19 00:43:15 +02:00
battlerId = gSprites[healthboxSpriteId].hMain_Battler;
2017-10-18 00:00:46 +02:00
2018-03-01 00:59:52 +01:00
if (gBattleSpritesDataPtr->battlerData[battlerId].hpNumbersNoBars) // don't print text if only bars are visible
2017-10-18 00:00:46 +02:00
{
u8 var = 4;
u8 r7;
u8 *txtPtr;
u8 i;
2017-10-19 18:25:48 +02:00
if (maxOrCurrent == HP_CURRENT)
2017-10-18 00:00:46 +02:00
var = 0;
2017-12-02 21:44:50 +01:00
r7 = gSprites[healthboxSpriteId].data[5];
2017-10-18 00:00:46 +02:00
txtPtr = ConvertIntToDecimalStringN(text + 6, value, STR_CONV_MODE_RIGHT_ALIGN, 3);
if (!maxOrCurrent)
StringCopy(txtPtr, gText_Slash);
2017-11-04 16:25:19 +01:00
RenderTextFont9(gMonSpritesGfxPtr->barFontGfx, 9, text);
2017-10-18 00:00:46 +02:00
for (i = var; i < var + 3; i++)
{
if (i < 3)
{
2017-11-04 16:25:19 +01:00
CpuCopy32(&gMonSpritesGfxPtr->barFontGfx[((i - var) * 64) + 32],
2017-10-18 00:00:46 +02:00
(void*)((OBJ_VRAM0) + 32 * (1 + gSprites[r7].oam.tileNum + i)),
0x20);
}
else
{
2017-11-04 16:25:19 +01:00
CpuCopy32(&gMonSpritesGfxPtr->barFontGfx[((i - var) * 64) + 32],
2017-10-18 00:00:46 +02:00
(void*)((OBJ_VRAM0 + 0x20) + 32 * (i + gSprites[r7].oam.tileNum)),
0x20);
}
}
2017-10-19 18:25:48 +02:00
if (maxOrCurrent == HP_CURRENT)
2017-10-18 00:00:46 +02:00
{
2017-11-04 16:25:19 +01:00
CpuCopy32(&gMonSpritesGfxPtr->barFontGfx[224],
2018-11-22 02:10:50 +01:00
(void*)((OBJ_VRAM0) + ((gSprites[r7].oam.tileNum + 4) * TILE_SIZE_4BPP)),
2017-10-18 00:00:46 +02:00
0x20);
2018-11-22 02:10:50 +01:00
CpuFill32(0, (void*)((OBJ_VRAM0) + (gSprites[r7].oam.tileNum * TILE_SIZE_4BPP)), 0x20);
2017-10-18 00:00:46 +02:00
}
else
{
2018-06-19 00:43:15 +02:00
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) // Impossible to reach part, because the battlerId is from the opponent's side.
2017-10-18 00:00:46 +02:00
{
2017-10-19 18:25:48 +02:00
CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_116),
2018-11-22 02:10:50 +01:00
(void*)(OBJ_VRAM0) + ((gSprites[healthboxSpriteId].oam.tileNum + 52) * TILE_SIZE_4BPP),
2017-10-18 00:00:46 +02:00
0x20);
}
}
}
}
}
2017-10-18 21:42:00 +02:00
2018-07-01 11:15:42 +02:00
// Prints mon's nature, catch and flee rate. Probably used to test pokeblock-related features.
2018-06-19 00:43:15 +02:00
static void PrintSafariMonInfo(u8 healthboxSpriteId, struct Pokemon *mon)
2017-10-18 21:42:00 +02:00
{
u8 text[20];
2018-11-22 02:10:50 +01:00
s32 j, spriteTileNum;
2017-11-04 16:25:19 +01:00
u8 *barFontGfx;
2018-06-19 00:43:15 +02:00
u8 i, var, nature, healthBarSpriteId;
2017-10-18 21:42:00 +02:00
2017-10-20 19:24:46 +02:00
memcpy(text, sUnknown_0832C3C4, sizeof(sUnknown_0832C3C4));
2018-06-19 00:43:15 +02:00
barFontGfx = &gMonSpritesGfxPtr->barFontGfx[0x520 + (GetBattlerPosition(gSprites[healthboxSpriteId].hMain_Battler) * 384)];
2017-10-18 21:42:00 +02:00
var = 5;
nature = GetNature(mon);
StringCopy(text + 6, gNatureNamePointers[nature]);
2017-11-04 16:25:19 +01:00
RenderTextFont9(barFontGfx, 9, text);
2017-10-18 21:42:00 +02:00
for (j = 6, i = 0; i < var; i++, j++)
{
u8 elementId;
if ((text[j] >= 55 && text[j] <= 74) || (text[j] >= 135 && text[j] <= 154))
elementId = 44;
else if ((text[j] >= 75 && text[j] <= 79) || (text[j] >= 155 && text[j] <= 159))
elementId = 45;
else
elementId = 43;
2017-11-04 16:25:19 +01:00
CpuCopy32(GetHealthboxElementGfxPtr(elementId), barFontGfx + (i * 64), 0x20);
2017-10-18 21:42:00 +02:00
}
for (j = 1; j < var + 1; j++)
{
2018-11-22 02:10:50 +01:00
spriteTileNum = (gSprites[healthboxSpriteId].oam.tileNum + (j - (j / 8 * 8)) + (j / 8 * 64)) * TILE_SIZE_4BPP;
CpuCopy32(barFontGfx, (void*)(OBJ_VRAM0) + (spriteTileNum), 0x20);
2017-11-04 16:25:19 +01:00
barFontGfx += 0x20;
2017-10-18 21:42:00 +02:00
2018-11-22 02:10:50 +01:00
spriteTileNum = (8 + gSprites[healthboxSpriteId].oam.tileNum + (j - (j / 8 * 8)) + (j / 8 * 64)) * TILE_SIZE_4BPP;
CpuCopy32(barFontGfx, (void*)(OBJ_VRAM0) + (spriteTileNum), 0x20);
2017-11-04 16:25:19 +01:00
barFontGfx += 0x20;
2017-10-18 21:42:00 +02:00
}
2018-06-19 00:43:15 +02:00
healthBarSpriteId = gSprites[healthboxSpriteId].hMain_HealthBarSpriteId;
2018-07-01 11:15:42 +02:00
ConvertIntToDecimalStringN(text + 6, gBattleStruct->safariCatchFactor, STR_CONV_MODE_RIGHT_ALIGN, 2);
ConvertIntToDecimalStringN(text + 9, gBattleStruct->safariEscapeFactor, STR_CONV_MODE_RIGHT_ALIGN, 2);
2017-10-18 21:42:00 +02:00
text[5] = CHAR_SPACE;
text[8] = CHAR_SLASH;
2017-11-04 16:25:19 +01:00
RenderTextFont9(gMonSpritesGfxPtr->barFontGfx, 9, text);
2017-10-18 21:42:00 +02:00
2018-06-19 00:43:15 +02:00
j = healthBarSpriteId; // Needed to match for some reason.
2017-10-18 21:42:00 +02:00
for (j = 0; j < 5; j++)
{
if (j <= 1)
{
2017-11-04 16:25:19 +01:00
CpuCopy32(&gMonSpritesGfxPtr->barFontGfx[0x40 * j + 0x20],
2018-11-22 02:10:50 +01:00
(void*)(OBJ_VRAM0) + (gSprites[healthBarSpriteId].oam.tileNum + 2 + j) * TILE_SIZE_4BPP,
2017-10-18 21:42:00 +02:00
32);
}
else
{
2017-11-04 16:25:19 +01:00
CpuCopy32(&gMonSpritesGfxPtr->barFontGfx[0x40 * j + 0x20],
2018-11-22 02:10:50 +01:00
(void*)(OBJ_VRAM0 + 0xC0) + (j + gSprites[healthBarSpriteId].oam.tileNum) * TILE_SIZE_4BPP,
2017-10-18 21:42:00 +02:00
32);
}
}
}
void SwapHpBarsWithHpText(void)
{
s32 i;
2018-06-19 00:43:15 +02:00
u8 healthBarSpriteId;
2017-10-18 21:42:00 +02:00
2018-02-06 02:46:59 +01:00
for (i = 0; i < gBattlersCount; i++)
2017-10-18 21:42:00 +02:00
{
2018-02-06 20:48:02 +01:00
if (gSprites[gHealthboxSpriteIds[i]].callback == SpriteCallbackDummy
2018-02-06 02:46:59 +01:00
&& GetBattlerSide(i) != B_SIDE_OPPONENT
&& (IsDoubleBattle() || GetBattlerSide(i) != B_SIDE_PLAYER))
2017-10-18 21:42:00 +02:00
{
bool8 noBars;
2018-02-06 23:09:39 +01:00
gBattleSpritesDataPtr->battlerData[i].hpNumbersNoBars ^= 1;
noBars = gBattleSpritesDataPtr->battlerData[i].hpNumbersNoBars;
2018-02-06 02:46:59 +01:00
if (GetBattlerSide(i) == B_SIDE_PLAYER)
2017-10-18 21:42:00 +02:00
{
if (!IsDoubleBattle())
continue;
if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
continue;
if (noBars == TRUE) // bars to text
{
2018-06-19 00:43:15 +02:00
healthBarSpriteId = gSprites[gHealthboxSpriteIds[i]].hMain_HealthBarSpriteId;
2017-10-18 21:42:00 +02:00
2018-11-22 02:10:50 +01:00
CpuFill32(0, (void*)(OBJ_VRAM0 + gSprites[healthBarSpriteId].oam.tileNum * TILE_SIZE_4BPP), 0x100);
2018-02-06 20:48:02 +01:00
UpdateHpTextInHealthboxInDoubles(gHealthboxSpriteIds[i], GetMonData(&gPlayerParty[gBattlerPartyIndexes[i]], MON_DATA_HP), HP_CURRENT);
UpdateHpTextInHealthboxInDoubles(gHealthboxSpriteIds[i], GetMonData(&gPlayerParty[gBattlerPartyIndexes[i]], MON_DATA_MAX_HP), HP_MAX);
2017-10-18 21:42:00 +02:00
}
else // text to bars
{
2018-02-06 20:48:02 +01:00
UpdateStatusIconInHealthbox(gHealthboxSpriteIds[i]);
UpdateHealthboxAttribute(gHealthboxSpriteIds[i], &gPlayerParty[gBattlerPartyIndexes[i]], HEALTHBOX_HEALTH_BAR);
2018-11-22 02:10:50 +01:00
CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_117), (void*)(OBJ_VRAM0 + 0x680 + gSprites[gHealthboxSpriteIds[i]].oam.tileNum * TILE_SIZE_4BPP), 32);
2017-10-18 21:42:00 +02:00
}
}
else
{
if (noBars == TRUE) // bars to text
{
if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
{
2018-06-19 00:43:15 +02:00
// Most likely a debug function.
PrintSafariMonInfo(gHealthboxSpriteIds[i], &gEnemyParty[gBattlerPartyIndexes[i]]);
2017-10-18 21:42:00 +02:00
}
else
{
2018-06-19 00:43:15 +02:00
healthBarSpriteId = gSprites[gHealthboxSpriteIds[i]].hMain_HealthBarSpriteId;
2017-10-18 21:42:00 +02:00
2018-06-19 00:43:15 +02:00
CpuFill32(0, (void *)(OBJ_VRAM0 + gSprites[healthBarSpriteId].oam.tileNum * 32), 0x100);
2018-02-06 20:48:02 +01:00
UpdateHpTextInHealthboxInDoubles(gHealthboxSpriteIds[i], GetMonData(&gEnemyParty[gBattlerPartyIndexes[i]], MON_DATA_HP), HP_CURRENT);
UpdateHpTextInHealthboxInDoubles(gHealthboxSpriteIds[i], GetMonData(&gEnemyParty[gBattlerPartyIndexes[i]], MON_DATA_MAX_HP), HP_MAX);
2017-10-18 21:42:00 +02:00
}
}
else // text to bars
{
2018-02-06 20:48:02 +01:00
UpdateStatusIconInHealthbox(gHealthboxSpriteIds[i]);
UpdateHealthboxAttribute(gHealthboxSpriteIds[i], &gEnemyParty[gBattlerPartyIndexes[i]], HEALTHBOX_HEALTH_BAR);
2017-10-18 21:42:00 +02:00
if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
2018-02-06 20:48:02 +01:00
UpdateHealthboxAttribute(gHealthboxSpriteIds[i], &gEnemyParty[gBattlerPartyIndexes[i]], HEALTHBOX_NICK);
2017-10-18 21:42:00 +02:00
}
}
2018-06-19 00:43:15 +02:00
gSprites[gHealthboxSpriteIds[i]].hMain_Data7 ^= 1;
2017-10-18 21:42:00 +02:00
}
}
}
2018-09-17 22:40:49 +02:00
// Mega Evolution gfx functions.
2018-09-20 20:59:00 +02:00
void ChangeMegaTriggerSprite(u8 spriteId, u8 animId)
2018-09-17 22:40:49 +02:00
{
2018-09-20 20:59:00 +02:00
StartSpriteAnim(&gSprites[spriteId], animId);
2018-09-17 22:40:49 +02:00
}
2018-09-20 20:59:00 +02:00
#define SINGLES_MEGA_TRIGGER_POS_X_OPTIMAL (30)
#define SINGLES_MEGA_TRIGGER_POS_X_PRIORITY (31)
#define SINGLES_MEGA_TRIGGER_POS_X_SLIDE (15)
#define SINGLES_MEGA_TRIGGER_POS_Y_DIFF (-11)
#define DOUBLES_MEGA_TRIGGER_POS_X_OPTIMAL (30)
#define DOUBLES_MEGA_TRIGGER_POS_X_PRIORITY (31)
#define DOUBLES_MEGA_TRIGGER_POS_X_SLIDE (15)
#define DOUBLES_MEGA_TRIGGER_POS_Y_DIFF (-4)
2018-09-17 22:40:49 +02:00
#define tBattler data[0]
#define tHide data[1]
2018-09-17 22:40:49 +02:00
void CreateMegaTriggerSprite(u8 battlerId, u8 palId)
{
2018-09-20 20:59:00 +02:00
LoadSpritePalette(&sSpritePalette_MegaTrigger);
2018-09-17 22:40:49 +02:00
if (GetSpriteTileStartByTag(TAG_MEGA_TRIGGER_TILE) == 0xFFFF)
LoadSpriteSheet(&sSpriteSheet_MegaTrigger);
if (gBattleStruct->mega.triggerSpriteId == 0xFF)
2018-09-17 22:40:49 +02:00
{
2018-09-20 20:59:00 +02:00
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
gBattleStruct->mega.triggerSpriteId = CreateSprite(&sSpriteTemplate_MegaTrigger,
gSprites[gHealthboxSpriteIds[battlerId]].pos1.x - DOUBLES_MEGA_TRIGGER_POS_X_SLIDE,
gSprites[gHealthboxSpriteIds[battlerId]].pos1.y - DOUBLES_MEGA_TRIGGER_POS_Y_DIFF, 0);
2018-09-22 01:01:13 +02:00
else
gBattleStruct->mega.triggerSpriteId = CreateSprite(&sSpriteTemplate_MegaTrigger,
gSprites[gHealthboxSpriteIds[battlerId]].pos1.x - SINGLES_MEGA_TRIGGER_POS_X_SLIDE,
gSprites[gHealthboxSpriteIds[battlerId]].pos1.y - SINGLES_MEGA_TRIGGER_POS_Y_DIFF, 0);
2018-09-17 22:40:49 +02:00
}
gSprites[gBattleStruct->mega.triggerSpriteId].tBattler = battlerId;
gSprites[gBattleStruct->mega.triggerSpriteId].tHide = FALSE;
2018-09-17 22:40:49 +02:00
2018-09-20 20:59:00 +02:00
ChangeMegaTriggerSprite(gBattleStruct->mega.triggerSpriteId, palId);
2018-09-17 22:40:49 +02:00
}
static void SpriteCb_MegaTrigger(struct Sprite *sprite)
{
2018-09-20 20:59:00 +02:00
s32 xSlide, xPriority, xOptimal;
s32 yDiff;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
xSlide = DOUBLES_MEGA_TRIGGER_POS_X_SLIDE;
xPriority = DOUBLES_MEGA_TRIGGER_POS_X_PRIORITY;
xOptimal = DOUBLES_MEGA_TRIGGER_POS_X_OPTIMAL;
yDiff = DOUBLES_MEGA_TRIGGER_POS_Y_DIFF;
}
else
{
xSlide = SINGLES_MEGA_TRIGGER_POS_X_SLIDE;
xPriority = SINGLES_MEGA_TRIGGER_POS_X_PRIORITY;
xOptimal = SINGLES_MEGA_TRIGGER_POS_X_OPTIMAL;
yDiff = SINGLES_MEGA_TRIGGER_POS_Y_DIFF;
}
if (sprite->tHide)
{
2018-09-20 20:59:00 +02:00
if (sprite->pos1.x != gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos1.x - xSlide)
sprite->pos1.x++;
2018-09-22 01:01:13 +02:00
if (sprite->pos1.x >= gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos1.x - xPriority)
2018-09-20 20:59:00 +02:00
sprite->oam.priority = 2;
else
sprite->oam.priority = 1;
sprite->pos1.y = gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos1.y - yDiff;
sprite->pos2.y = gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos2.y - yDiff;
if (sprite->pos1.x == gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos1.x - xSlide)
DestroyMegaTriggerSprite();
}
else
{
2018-09-20 20:59:00 +02:00
if (sprite->pos1.x != gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos1.x - xOptimal)
sprite->pos1.x--;
2018-09-22 01:01:13 +02:00
if (sprite->pos1.x >= gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos1.x - xPriority)
2018-09-20 20:59:00 +02:00
sprite->oam.priority = 2;
else
sprite->oam.priority = 1;
sprite->pos1.y = gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos1.y - yDiff;
sprite->pos2.y = gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos2.y - yDiff;
}
}
bool32 IsMegaTriggerSpriteActive(void)
{
if (GetSpriteTileStartByTag(TAG_MEGA_TRIGGER_TILE) == 0xFFFF)
return FALSE;
2018-09-20 20:59:00 +02:00
else if (IndexOfSpritePaletteTag(TAG_MEGA_TRIGGER_PAL) != 0xFF)
return TRUE;
else
return FALSE;
}
2018-09-17 22:40:49 +02:00
void HideMegaTriggerSprite(void)
{
2018-09-20 20:59:00 +02:00
ChangeMegaTriggerSprite(gBattleStruct->mega.triggerSpriteId, 0);
gSprites[gBattleStruct->mega.triggerSpriteId].tHide = TRUE;
2018-09-17 22:40:49 +02:00
}
void DestroyMegaTriggerSprite(void)
{
2018-09-20 20:59:00 +02:00
FreeSpritePaletteByTag(TAG_MEGA_TRIGGER_PAL);
2018-09-17 22:40:49 +02:00
FreeSpriteTilesByTag(TAG_MEGA_TRIGGER_TILE);
if (gBattleStruct->mega.triggerSpriteId != 0xFF)
DestroySprite(&gSprites[gBattleStruct->mega.triggerSpriteId]);
gBattleStruct->mega.triggerSpriteId = 0xFF;
2018-09-17 22:40:49 +02:00
}
#undef tBattler
#undef tHide
2018-06-20 23:07:51 +02:00
#define tBattler data[0]
#define tSummaryBarSpriteId data[1]
#define tBallIconSpriteId(n) data[3 + n]
#define tIsBattleStart data[10]
#define tData15 data[15]
2018-03-01 00:59:52 +01:00
u8 CreatePartyStatusSummarySprites(u8 battlerId, struct HpAndStatus *partyInfo, u8 arg2, bool8 isBattleStart)
2017-10-18 21:42:00 +02:00
{
bool8 isOpponent;
s16 bar_X, bar_Y, bar_pos2_X, bar_data0;
s32 i, j, var;
2018-06-20 23:07:51 +02:00
u8 summaryBarSpriteId;
2018-06-19 00:43:15 +02:00
u8 ballIconSpritesIds[PARTY_SIZE];
2017-10-18 21:42:00 +02:00
u8 taskId;
2018-03-01 00:59:52 +01:00
if (!arg2 || GetBattlerPosition(battlerId) != B_POSITION_OPPONENT_RIGHT)
2017-10-18 21:42:00 +02:00
{
2018-03-01 00:59:52 +01:00
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
2017-10-18 21:42:00 +02:00
{
isOpponent = FALSE;
bar_X = 136, bar_Y = 96;
bar_pos2_X = 100;
bar_data0 = -5;
}
else
{
isOpponent = TRUE;
if (!arg2 || !IsDoubleBattle())
bar_X = 104, bar_Y = 40;
else
bar_X = 104, bar_Y = 16;
bar_pos2_X = -100;
bar_data0 = 5;
}
}
else
{
isOpponent = TRUE;
bar_X = 104, bar_Y = 40;
bar_pos2_X = -100;
bar_data0 = 5;
}
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheetUsingHeap(&sStatusSummaryBarSpriteSheet);
2017-10-19 18:25:48 +02:00
LoadSpriteSheet(&sStatusSummaryBallsSpriteSheet);
LoadSpritePalette(&sStatusSummaryBarSpritePal);
LoadSpritePalette(&sStatusSummaryBallsSpritePal);
2017-10-18 21:42:00 +02:00
2018-06-20 23:07:51 +02:00
summaryBarSpriteId = CreateSprite(&sStatusSummaryBarSpriteTemplates[isOpponent], bar_X, bar_Y, 10);
SetSubspriteTables(&gSprites[summaryBarSpriteId], sStatusSummaryBar_SubspriteTable);
gSprites[summaryBarSpriteId].pos2.x = bar_pos2_X;
gSprites[summaryBarSpriteId].data[0] = bar_data0;
2017-10-18 21:42:00 +02:00
if (isOpponent)
{
2018-06-20 23:07:51 +02:00
gSprites[summaryBarSpriteId].pos1.x -= 96;
gSprites[summaryBarSpriteId].oam.matrixNum = 8;
2017-10-18 21:42:00 +02:00
}
else
{
2018-06-20 23:07:51 +02:00
gSprites[summaryBarSpriteId].pos1.x += 96;
2017-10-18 21:42:00 +02:00
}
2018-02-08 11:17:41 +01:00
for (i = 0; i < PARTY_SIZE; i++)
2017-10-18 21:42:00 +02:00
{
2017-10-19 18:25:48 +02:00
ballIconSpritesIds[i] = CreateSpriteAtEnd(&sStatusSummaryBallsSpriteTemplates[isOpponent], bar_X, bar_Y - 4, 9);
2017-10-18 21:42:00 +02:00
if (!isBattleStart)
2017-10-19 18:25:48 +02:00
gSprites[ballIconSpritesIds[i]].callback = SpriteCB_StatusSummaryBallsOnSwitchout;
2017-10-18 21:42:00 +02:00
if (!isOpponent)
{
gSprites[ballIconSpritesIds[i]].pos2.x = 0;
gSprites[ballIconSpritesIds[i]].pos2.y = 0;
}
2018-06-20 23:07:51 +02:00
gSprites[ballIconSpritesIds[i]].data[0] = summaryBarSpriteId;
2017-10-18 21:42:00 +02:00
if (!isOpponent)
{
gSprites[ballIconSpritesIds[i]].pos1.x += 10 * i + 24;
2017-12-02 21:44:50 +01:00
gSprites[ballIconSpritesIds[i]].data[1] = i * 7 + 10;
2017-10-18 21:42:00 +02:00
gSprites[ballIconSpritesIds[i]].pos2.x = 120;
}
else
{
gSprites[ballIconSpritesIds[i]].pos1.x -= 10 * (5 - i) + 24;
2017-12-02 21:44:50 +01:00
gSprites[ballIconSpritesIds[i]].data[1] = (6 - i) * 7 + 10;
2017-10-18 21:42:00 +02:00
gSprites[ballIconSpritesIds[i]].pos2.x = -120;
}
2017-12-02 21:44:50 +01:00
gSprites[ballIconSpritesIds[i]].data[2] = isOpponent;
2017-10-18 21:42:00 +02:00
}
2018-03-01 00:59:52 +01:00
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
2017-10-18 21:42:00 +02:00
{
if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
{
2018-06-19 00:43:15 +02:00
for (i = 0; i < PARTY_SIZE; i++)
2017-10-18 21:42:00 +02:00
{
if (partyInfo[i].hp == 0xFFFF) // empty slot or an egg
{
gSprites[ballIconSpritesIds[i]].oam.tileNum += 1;
2017-12-02 21:44:50 +01:00
gSprites[ballIconSpritesIds[i]].data[7] = 1;
2017-10-18 21:42:00 +02:00
}
else if (partyInfo[i].hp == 0) // fainted mon
{
gSprites[ballIconSpritesIds[i]].oam.tileNum += 3;
}
else if (partyInfo[i].status != 0) // mon with major status
{
gSprites[ballIconSpritesIds[i]].oam.tileNum += 2;
}
}
}
else
{
2018-06-19 00:43:15 +02:00
for (i = 0, var = 5, j = 0; j < PARTY_SIZE; j++)
2017-10-18 21:42:00 +02:00
{
if (partyInfo[j].hp == 0xFFFF) // empty slot or an egg
{
gSprites[ballIconSpritesIds[var]].oam.tileNum += 1;
2017-12-02 21:44:50 +01:00
gSprites[ballIconSpritesIds[var]].data[7] = 1;
2017-10-18 21:42:00 +02:00
var--;
continue;
}
else if (partyInfo[j].hp == 0) // fainted mon
{
gSprites[ballIconSpritesIds[i]].oam.tileNum += 3;
}
2018-11-11 18:33:16 +01:00
else if (gBattleTypeFlags & BATTLE_TYPE_ARENA && gBattleStruct->arenaLostPlayerMons & gBitTable[j])
2017-10-18 21:42:00 +02:00
{
gSprites[ballIconSpritesIds[i]].oam.tileNum += 3;
}
else if (partyInfo[j].status != 0) // mon with major status
{
gSprites[ballIconSpritesIds[i]].oam.tileNum += 2;
}
i++;
}
}
}
else
{
if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS))
{
2018-06-19 00:43:15 +02:00
for (var = 5, i = 0; i < PARTY_SIZE; i++)
2017-10-18 21:42:00 +02:00
{
if (partyInfo[i].hp == 0xFFFF) // empty slot or an egg
{
gSprites[ballIconSpritesIds[var]].oam.tileNum += 1;
2017-12-02 21:44:50 +01:00
gSprites[ballIconSpritesIds[var]].data[7] = 1;
2017-10-18 21:42:00 +02:00
}
else if (partyInfo[i].hp == 0) // fainted mon
{
gSprites[ballIconSpritesIds[var]].oam.tileNum += 3;
}
else if (partyInfo[i].status != 0) // mon with major status
{
gSprites[ballIconSpritesIds[var]].oam.tileNum += 2;
}
var--;
}
}
else
{
2018-06-19 00:43:15 +02:00
for (var = 0, i = 0, j = 0; j < PARTY_SIZE; j++)
2017-10-18 21:42:00 +02:00
{
if (partyInfo[j].hp == 0xFFFF) // empty slot or an egg
{
gSprites[ballIconSpritesIds[i]].oam.tileNum += 1;
2017-12-02 21:44:50 +01:00
gSprites[ballIconSpritesIds[i]].data[7] = 1;
2017-10-18 21:42:00 +02:00
i++;
continue;
}
else if (partyInfo[j].hp == 0) // fainted mon
{
gSprites[ballIconSpritesIds[5 - var]].oam.tileNum += 3;
}
2018-11-11 18:33:16 +01:00
else if (gBattleTypeFlags & BATTLE_TYPE_ARENA && gBattleStruct->arenaLostOpponentMons & gBitTable[j]) // hmm...?
2017-10-18 21:42:00 +02:00
{
gSprites[ballIconSpritesIds[5 - var]].oam.tileNum += 3;
}
else if (partyInfo[j].status != 0) // mon with major status
{
gSprites[ballIconSpritesIds[5 - var]].oam.tileNum += 2;
}
var++;
}
}
}
taskId = CreateTask(TaskDummy, 5);
2018-06-20 23:07:51 +02:00
gTasks[taskId].tBattler = battlerId;
gTasks[taskId].tSummaryBarSpriteId = summaryBarSpriteId;
2017-10-18 21:42:00 +02:00
2018-06-19 00:43:15 +02:00
for (i = 0; i < PARTY_SIZE; i++)
2018-06-20 23:07:51 +02:00
gTasks[taskId].tBallIconSpriteId(i) = ballIconSpritesIds[i];
2017-10-18 21:42:00 +02:00
2018-06-20 23:07:51 +02:00
gTasks[taskId].tIsBattleStart = isBattleStart;
2017-10-18 21:42:00 +02:00
if (isBattleStart)
{
gBattleSpritesDataPtr->animationData->field_9_x1C++;
}
PlaySE12WithPanning(SE_TB_START, 0);
return taskId;
}
2018-06-28 21:06:32 +02:00
void Task_HidePartyStatusSummary(u8 taskId)
2017-10-18 21:42:00 +02:00
{
2018-06-20 23:07:51 +02:00
u8 ballIconSpriteIds[PARTY_SIZE];
bool8 isBattleStart;
2018-06-19 00:43:15 +02:00
u8 summaryBarSpriteId;
2018-03-01 00:59:52 +01:00
u8 battlerId;
2017-10-18 21:42:00 +02:00
s32 i;
2018-06-20 23:07:51 +02:00
isBattleStart = gTasks[taskId].tIsBattleStart;
summaryBarSpriteId = gTasks[taskId].tSummaryBarSpriteId;
battlerId = gTasks[taskId].tBattler;
2017-10-18 21:42:00 +02:00
2018-06-28 21:06:32 +02:00
for (i = 0; i < PARTY_SIZE; i++)
2018-06-20 23:07:51 +02:00
ballIconSpriteIds[i] = gTasks[taskId].tBallIconSpriteId(i);
2017-10-18 21:42:00 +02:00
2018-07-16 20:47:30 +02:00
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND);
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0));
2017-10-18 21:42:00 +02:00
2018-06-20 23:07:51 +02:00
gTasks[taskId].tData15 = 16;
2017-10-18 21:42:00 +02:00
2018-06-20 23:07:51 +02:00
for (i = 0; i < PARTY_SIZE; i++)
gSprites[ballIconSpriteIds[i]].oam.objMode = 1;
2017-10-18 21:42:00 +02:00
2018-06-19 00:43:15 +02:00
gSprites[summaryBarSpriteId].oam.objMode = 1;
2017-10-18 21:42:00 +02:00
2018-06-20 23:07:51 +02:00
if (isBattleStart)
2017-10-18 21:42:00 +02:00
{
2018-06-20 23:07:51 +02:00
for (i = 0; i < PARTY_SIZE; i++)
2017-10-18 21:42:00 +02:00
{
2018-03-01 00:59:52 +01:00
if (GetBattlerSide(battlerId) != B_SIDE_PLAYER)
2017-10-18 21:42:00 +02:00
{
2018-06-20 23:07:51 +02:00
gSprites[ballIconSpriteIds[5 - i]].data[1] = 7 * i;
gSprites[ballIconSpriteIds[5 - i]].data[3] = 0;
gSprites[ballIconSpriteIds[5 - i]].data[4] = 0;
gSprites[ballIconSpriteIds[5 - i]].callback = sub_8074158;
2017-10-18 21:42:00 +02:00
}
else
{
2018-06-20 23:07:51 +02:00
gSprites[ballIconSpriteIds[i]].data[1] = 7 * i;
gSprites[ballIconSpriteIds[i]].data[3] = 0;
gSprites[ballIconSpriteIds[i]].data[4] = 0;
gSprites[ballIconSpriteIds[i]].callback = sub_8074158;
2017-10-18 21:42:00 +02:00
}
}
2018-06-19 00:43:15 +02:00
gSprites[summaryBarSpriteId].data[0] /= 2;
gSprites[summaryBarSpriteId].data[1] = 0;
gSprites[summaryBarSpriteId].callback = sub_8074090;
SetSubspriteTables(&gSprites[summaryBarSpriteId], sUnknown_0832C2CC);
2017-10-18 21:42:00 +02:00
gTasks[taskId].func = sub_8073E08;
}
else
{
gTasks[taskId].func = sub_8073F98;
}
}
2017-10-19 15:28:41 +02:00
static void sub_8073E08(u8 taskId)
2017-10-18 21:42:00 +02:00
{
2018-06-20 23:07:51 +02:00
if ((gTasks[taskId].data[11]++ % 2) == 0)
2017-10-18 21:42:00 +02:00
{
2018-06-28 21:06:32 +02:00
if (--gTasks[taskId].tData15 < 0)
2017-10-18 21:42:00 +02:00
return;
2018-12-26 14:03:48 +01:00
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[15], 16 - gTasks[taskId].data[15]));
2017-10-18 21:42:00 +02:00
}
2018-06-28 21:06:32 +02:00
if (gTasks[taskId].tData15 == 0)
2017-10-18 21:42:00 +02:00
gTasks[taskId].func = sub_8073E64;
}
2017-10-19 15:28:41 +02:00
static void sub_8073E64(u8 taskId)
2017-10-18 21:42:00 +02:00
{
2018-06-20 23:07:51 +02:00
u8 ballIconSpriteIds[PARTY_SIZE];
2017-10-18 21:42:00 +02:00
s32 i;
2018-06-20 23:07:51 +02:00
u8 battlerId = gTasks[taskId].tBattler;
if (--gTasks[taskId].tData15 == -1)
2017-10-18 21:42:00 +02:00
{
2018-06-20 23:07:51 +02:00
u8 summaryBarSpriteId = gTasks[taskId].tSummaryBarSpriteId;
2017-10-18 21:42:00 +02:00
2018-06-20 23:07:51 +02:00
for (i = 0; i < PARTY_SIZE; i++)
ballIconSpriteIds[i] = gTasks[taskId].tBallIconSpriteId(i);
2017-10-18 21:42:00 +02:00
gBattleSpritesDataPtr->animationData->field_9_x1C--;
2018-06-20 23:07:51 +02:00
if (gBattleSpritesDataPtr->animationData->field_9_x1C == 0)
2017-10-18 21:42:00 +02:00
{
2018-06-19 00:43:15 +02:00
DestroySpriteAndFreeResources(&gSprites[summaryBarSpriteId]);
2018-06-20 23:07:51 +02:00
DestroySpriteAndFreeResources(&gSprites[ballIconSpriteIds[0]]);
2017-10-18 21:42:00 +02:00
}
else
{
2018-06-19 00:43:15 +02:00
FreeSpriteOamMatrix(&gSprites[summaryBarSpriteId]);
DestroySprite(&gSprites[summaryBarSpriteId]);
2018-06-20 23:07:51 +02:00
FreeSpriteOamMatrix(&gSprites[ballIconSpriteIds[0]]);
DestroySprite(&gSprites[ballIconSpriteIds[0]]);
2017-10-18 21:42:00 +02:00
}
2018-06-20 23:07:51 +02:00
for (i = 1; i < PARTY_SIZE; i++)
DestroySprite(&gSprites[ballIconSpriteIds[i]]);
2017-10-18 21:42:00 +02:00
}
2018-06-20 23:07:51 +02:00
else if (gTasks[taskId].tData15 == -3)
2017-10-18 21:42:00 +02:00
{
2018-06-28 21:06:32 +02:00
gBattleSpritesDataPtr->healthBoxesData[battlerId].partyStatusSummaryShown = 0;
2017-10-18 21:42:00 +02:00
SetGpuReg(REG_OFFSET_BLDCNT, 0);
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
DestroyTask(taskId);
}
}
2017-10-19 15:28:41 +02:00
static void sub_8073F98(u8 taskId)
2017-10-18 21:42:00 +02:00
{
2018-06-20 23:07:51 +02:00
u8 ballIconSpriteIds[PARTY_SIZE];
2017-10-18 21:42:00 +02:00
s32 i;
2018-06-20 23:07:51 +02:00
u8 battlerId = gTasks[taskId].tBattler;
2017-10-18 21:42:00 +02:00
2018-06-20 23:07:51 +02:00
if (--gTasks[taskId].tData15 >= 0)
2017-10-18 21:42:00 +02:00
{
2018-12-26 14:03:48 +01:00
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[15], 16 - gTasks[taskId].data[15]));
2017-10-18 21:42:00 +02:00
}
2018-06-20 23:07:51 +02:00
else if (gTasks[taskId].tData15 == -1)
2017-10-18 21:42:00 +02:00
{
2018-06-20 23:07:51 +02:00
u8 summaryBarSpriteId = gTasks[taskId].tSummaryBarSpriteId;
2017-10-18 21:42:00 +02:00
2018-06-20 23:07:51 +02:00
for (i = 0; i < PARTY_SIZE; i++)
ballIconSpriteIds[i] = gTasks[taskId].tBallIconSpriteId(i);
2017-10-18 21:42:00 +02:00
2018-06-19 00:43:15 +02:00
DestroySpriteAndFreeResources(&gSprites[summaryBarSpriteId]);
2018-06-20 23:07:51 +02:00
DestroySpriteAndFreeResources(&gSprites[ballIconSpriteIds[0]]);
2017-10-18 21:42:00 +02:00
2018-06-20 23:07:51 +02:00
for (i = 1; i < PARTY_SIZE; i++)
DestroySprite(&gSprites[ballIconSpriteIds[i]]);
2017-10-18 21:42:00 +02:00
}
2018-06-20 23:07:51 +02:00
else if (gTasks[taskId].tData15 == -3)
2017-10-18 21:42:00 +02:00
{
2018-06-28 21:06:32 +02:00
gBattleSpritesDataPtr->healthBoxesData[battlerId].partyStatusSummaryShown = 0;
2017-10-18 21:42:00 +02:00
SetGpuReg(REG_OFFSET_BLDCNT, 0);
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
DestroyTask(taskId);
}
}
2018-06-20 23:07:51 +02:00
#undef tBattler
#undef tSummaryBarSpriteId
#undef tBallIconSpriteId
#undef tIsBattleStart
#undef tData15
2017-10-19 18:25:48 +02:00
static void SpriteCB_StatusSummaryBar(struct Sprite *sprite)
2017-10-18 21:42:00 +02:00
{
if (sprite->pos2.x != 0)
2017-12-02 21:44:50 +01:00
sprite->pos2.x += sprite->data[0];
2017-10-18 21:42:00 +02:00
}
2017-10-19 15:28:41 +02:00
static void sub_8074090(struct Sprite *sprite)
2017-10-18 21:42:00 +02:00
{
2017-12-02 21:44:50 +01:00
sprite->data[1] += 32;
if (sprite->data[0] > 0)
sprite->pos2.x += sprite->data[1] >> 4;
2017-10-18 21:42:00 +02:00
else
2017-12-02 21:44:50 +01:00
sprite->pos2.x -= sprite->data[1] >> 4;
sprite->data[1] &= 0xF;
2017-10-18 21:42:00 +02:00
}
2017-10-19 18:25:48 +02:00
static void SpriteCB_StatusSummaryBallsOnBattleStart(struct Sprite *sprite)
2017-10-18 21:42:00 +02:00
{
u8 var1;
u16 var2;
s8 pan;
2017-12-02 21:44:50 +01:00
if (sprite->data[1] > 0)
2017-10-18 21:42:00 +02:00
{
2017-12-02 21:44:50 +01:00
sprite->data[1]--;
2017-10-18 21:42:00 +02:00
return;
}
2017-10-19 18:25:48 +02:00
2017-12-02 21:44:50 +01:00
var1 = sprite->data[2];
var2 = sprite->data[3];
2017-10-18 21:42:00 +02:00
var2 += 56;
2017-12-02 21:44:50 +01:00
sprite->data[3] = var2 & 0xFFF0;
2017-10-19 18:25:48 +02:00
2017-10-18 21:42:00 +02:00
if (var1 != 0)
{
sprite->pos2.x += var2 >> 4;
if (sprite->pos2.x > 0)
sprite->pos2.x = 0;
}
else
{
sprite->pos2.x -= var2 >> 4;
if (sprite->pos2.x < 0)
sprite->pos2.x = 0;
}
2017-10-19 18:25:48 +02:00
2017-10-18 21:42:00 +02:00
if (sprite->pos2.x == 0)
{
pan = SOUND_PAN_TARGET;
2017-10-18 21:42:00 +02:00
if (var1 != 0)
pan = SOUND_PAN_ATTACKER;
2017-10-19 18:25:48 +02:00
2017-12-02 21:44:50 +01:00
if (sprite->data[7] != 0)
2017-10-18 21:42:00 +02:00
PlaySE2WithPanning(SE_TB_KARA, pan);
else
PlaySE1WithPanning(SE_TB_KON, pan);
2017-10-19 18:25:48 +02:00
2017-10-18 21:42:00 +02:00
sprite->callback = SpriteCallbackDummy;
}
}
2017-10-19 15:28:41 +02:00
static void sub_8074158(struct Sprite *sprite)
2017-10-18 21:42:00 +02:00
{
u8 var1;
u16 var2;
2017-12-02 21:44:50 +01:00
if (sprite->data[1] > 0)
2017-10-18 21:42:00 +02:00
{
2017-12-02 21:44:50 +01:00
sprite->data[1]--;
2017-10-18 21:42:00 +02:00
return;
}
2017-12-02 21:44:50 +01:00
var1 = sprite->data[2];
var2 = sprite->data[3];
2017-10-18 21:42:00 +02:00
var2 += 56;
2017-12-02 21:44:50 +01:00
sprite->data[3] = var2 & 0xFFF0;
2017-10-18 21:42:00 +02:00
if (var1 != 0)
sprite->pos2.x += var2 >> 4;
else
sprite->pos2.x -= var2 >> 4;
if (sprite->pos2.x + sprite->pos1.x > 248
|| sprite->pos2.x + sprite->pos1.x < -8)
{
sprite->invisible = TRUE;
sprite->callback = SpriteCallbackDummy;
}
}
2017-10-19 18:25:48 +02:00
static void SpriteCB_StatusSummaryBallsOnSwitchout(struct Sprite *sprite)
2017-10-18 21:42:00 +02:00
{
2017-12-02 21:44:50 +01:00
u8 barSpriteId = sprite->data[0];
2017-10-18 21:42:00 +02:00
sprite->pos2.x = gSprites[barSpriteId].pos2.x;
sprite->pos2.y = gSprites[barSpriteId].pos2.y;
}
2017-10-19 15:28:41 +02:00
static void UpdateNickInHealthbox(u8 healthboxSpriteId, struct Pokemon *mon)
2017-10-18 21:42:00 +02:00
{
u8 nickname[POKEMON_NAME_LENGTH + 1];
void *ptr;
const u8 *genderTxt;
2017-10-19 15:28:41 +02:00
u32 windowId, spriteTileNum;
u8 *windowTileData;
2017-10-18 21:42:00 +02:00
u16 species;
u8 gender;
StringCopy(gDisplayedStringBattle, gText_HighlightDarkGrey);
GetMonData(mon, MON_DATA_NICKNAME, nickname);
StringGetEnd10(nickname);
ptr = StringAppend(gDisplayedStringBattle, nickname);
gender = GetMonGender(mon);
species = GetMonData(mon, MON_DATA_SPECIES);
if ((species == SPECIES_NIDORAN_F || species == SPECIES_NIDORAN_M) && StringCompare(nickname, gSpeciesNames[species]) == 0)
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:
StringCopy(ptr, gText_DynColor2);
windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(gDisplayedStringBattle, 0, 3, 2, &windowId);
break;
case MON_MALE:
StringCopy(ptr, gText_DynColor2Male);
windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(gDisplayedStringBattle, 0, 3, 2, &windowId);
break;
case MON_FEMALE:
StringCopy(ptr, gText_DynColor1Female);
windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(gDisplayedStringBattle, 0, 3, 2, &windowId);
break;
}
2018-11-22 02:10:50 +01:00
spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * TILE_SIZE_4BPP;
2017-10-18 21:42:00 +02:00
2018-02-06 02:46:59 +01:00
if (GetBattlerSide(gSprites[healthboxSpriteId].data[6]) == B_SIDE_PLAYER)
2017-10-18 21:42:00 +02:00
{
2018-06-19 00:43:15 +02:00
TextIntoHealthboxObject((void*)(VRAM + 0x10040 + spriteTileNum), windowTileData, 6);
2017-10-18 21:42:00 +02:00
ptr = (void*)(OBJ_VRAM0);
if (!IsDoubleBattle())
ptr += spriteTileNum + 0x800;
else
ptr += spriteTileNum + 0x400;
2018-06-19 00:43:15 +02:00
TextIntoHealthboxObject(ptr, windowTileData + 0xC0, 1);
2017-10-18 21:42:00 +02:00
}
else
{
2018-06-19 00:43:15 +02:00
TextIntoHealthboxObject((void*)(VRAM + 0x10020 + spriteTileNum), windowTileData, 7);
2017-10-18 21:42:00 +02:00
}
2017-10-18 23:05:14 +02:00
RemoveWindowOnHealthbox(windowId);
}
2017-10-19 15:28:41 +02:00
static void TryAddPokeballIconToHealthbox(u8 healthboxSpriteId, bool8 noStatus)
2017-10-18 23:05:14 +02:00
{
2018-06-19 00:43:15 +02:00
u8 battlerId, healthBarSpriteId;
2017-10-18 23:05:14 +02:00
if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL)
return;
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
return;
2018-06-19 00:43:15 +02:00
battlerId = gSprites[healthboxSpriteId].hMain_Battler;
2018-03-01 00:59:52 +01:00
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
2017-10-18 23:05:14 +02:00
return;
2018-03-01 00:59:52 +01:00
if (!GetSetPokedexFlag(SpeciesToNationalPokedexNum(GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES)), FLAG_GET_CAUGHT))
2017-10-18 23:05:14 +02:00
return;
2018-06-19 00:43:15 +02:00
healthBarSpriteId = gSprites[healthboxSpriteId].hMain_HealthBarSpriteId;
2017-10-18 23:05:14 +02:00
if (noStatus)
2018-11-22 02:10:50 +01:00
CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_70), (void*)(OBJ_VRAM0 + (gSprites[healthBarSpriteId].oam.tileNum + 8) * TILE_SIZE_4BPP), 32);
2017-10-18 23:05:14 +02:00
else
2018-11-22 02:10:50 +01:00
CpuFill32(0, (void*)(OBJ_VRAM0 + (gSprites[healthBarSpriteId].oam.tileNum + 8) * TILE_SIZE_4BPP), 32);
2017-10-18 23:05:14 +02:00
}
2017-10-19 15:28:41 +02:00
static void UpdateStatusIconInHealthbox(u8 healthboxSpriteId)
2017-10-18 23:05:14 +02:00
{
s32 i;
2018-06-19 00:43:15 +02:00
u8 battlerId, healthBarSpriteId;
2017-10-18 23:05:14 +02:00
u32 status, pltAdder;
2017-10-19 15:28:41 +02:00
const u8 *statusGfxPtr;
2017-10-18 23:05:14 +02:00
s16 tileNumAdder;
u8 statusPalId;
2018-06-19 00:43:15 +02:00
battlerId = gSprites[healthboxSpriteId].hMain_Battler;
healthBarSpriteId = gSprites[healthboxSpriteId].hMain_HealthBarSpriteId;
2018-03-01 00:59:52 +01:00
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
2017-10-18 23:05:14 +02:00
{
2018-03-01 00:59:52 +01:00
status = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_STATUS);
2017-10-18 23:05:14 +02:00
if (!IsDoubleBattle())
tileNumAdder = 0x1A;
else
tileNumAdder = 0x12;
}
else
{
2018-03-01 00:59:52 +01:00
status = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_STATUS);
2017-10-18 23:05:14 +02:00
tileNumAdder = 0x11;
}
2018-01-16 22:12:38 +01:00
if (status & STATUS1_SLEEP)
2017-10-18 23:05:14 +02:00
{
2018-06-19 00:43:15 +02:00
statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_SLP_BATTLER0, battlerId));
2017-10-19 15:28:41 +02:00
statusPalId = PAL_STATUS_SLP;
2017-10-18 23:05:14 +02:00
}
2018-01-16 22:12:38 +01:00
else if (status & STATUS1_PSN_ANY)
2017-10-18 23:05:14 +02:00
{
2018-06-19 00:43:15 +02:00
statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_PSN_BATTLER0, battlerId));
2017-10-19 15:28:41 +02:00
statusPalId = PAL_STATUS_PSN;
2017-10-18 23:05:14 +02:00
}
2018-01-16 22:12:38 +01:00
else if (status & STATUS1_BURN)
2017-10-18 23:05:14 +02:00
{
2018-06-19 00:43:15 +02:00
statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_BRN_BATTLER0, battlerId));
2017-10-19 15:28:41 +02:00
statusPalId = PAL_STATUS_BRN;
2017-10-18 23:05:14 +02:00
}
2018-01-16 22:12:38 +01:00
else if (status & STATUS1_FREEZE)
2017-10-18 23:05:14 +02:00
{
2018-06-19 00:43:15 +02:00
statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_FRZ_BATTLER0, battlerId));
2017-10-19 15:28:41 +02:00
statusPalId = PAL_STATUS_FRZ;
2017-10-18 23:05:14 +02:00
}
2018-01-16 22:12:38 +01:00
else if (status & STATUS1_PARALYSIS)
2017-10-18 23:05:14 +02:00
{
2018-06-19 00:43:15 +02:00
statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_PRZ_BATTLER0, battlerId));
2017-10-19 15:28:41 +02:00
statusPalId = PAL_STATUS_PAR;
2017-10-18 23:05:14 +02:00
}
else
{
2017-10-19 18:25:48 +02:00
statusGfxPtr = GetHealthboxElementGfxPtr(HEALTHBOX_GFX_39);
2017-10-18 23:05:14 +02:00
for (i = 0; i < 3; i++)
2018-11-22 02:10:50 +01:00
CpuCopy32(statusGfxPtr, (void*)(OBJ_VRAM0 + (gSprites[healthboxSpriteId].oam.tileNum + tileNumAdder + i) * TILE_SIZE_4BPP), 32);
2017-10-18 23:05:14 +02:00
2018-03-01 00:59:52 +01:00
if (!gBattleSpritesDataPtr->battlerData[battlerId].hpNumbersNoBars)
2018-11-22 02:10:50 +01:00
CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_1), (void *)(OBJ_VRAM0 + gSprites[healthBarSpriteId].oam.tileNum * TILE_SIZE_4BPP), 64);
2017-10-18 23:05:14 +02:00
TryAddPokeballIconToHealthbox(healthboxSpriteId, TRUE);
return;
}
pltAdder = gSprites[healthboxSpriteId].oam.paletteNum * 16;
2018-03-01 00:59:52 +01:00
pltAdder += battlerId + 12;
2017-10-18 23:05:14 +02:00
2018-01-29 14:36:13 +01:00
FillPalette(sStatusIconColors[statusPalId], pltAdder + 0x100, 2);
2017-10-18 23:05:14 +02:00
CpuCopy16(gPlttBufferUnfaded + 0x100 + pltAdder, (void*)(OBJ_PLTT + pltAdder * 2), 2);
2018-11-22 02:10:50 +01:00
CpuCopy32(statusGfxPtr, (void*)(OBJ_VRAM0 + (gSprites[healthboxSpriteId].oam.tileNum + tileNumAdder) * TILE_SIZE_4BPP), 96);
2018-03-01 00:59:52 +01:00
if (IsDoubleBattle() == TRUE || GetBattlerSide(battlerId) == B_SIDE_OPPONENT)
2017-10-18 23:05:14 +02:00
{
2018-03-01 00:59:52 +01:00
if (!gBattleSpritesDataPtr->battlerData[battlerId].hpNumbersNoBars)
2017-10-18 23:05:14 +02:00
{
2018-11-22 02:10:50 +01:00
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);
2017-10-18 23:05:14 +02:00
}
}
TryAddPokeballIconToHealthbox(healthboxSpriteId, FALSE);
}
2018-06-19 00:43:15 +02:00
static u8 GetStatusIconForBattlerId(u8 statusElementId, u8 battlerId)
2017-10-18 23:05:14 +02:00
{
u8 ret = statusElementId;
switch (statusElementId)
{
2018-06-19 00:43:15 +02:00
case HEALTHBOX_GFX_STATUS_PSN_BATTLER0:
2018-03-01 00:59:52 +01:00
if (battlerId == 0)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_PSN_BATTLER0;
2018-03-01 00:59:52 +01:00
else if (battlerId == 1)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_PSN_BATTLER1;
2018-03-01 00:59:52 +01:00
else if (battlerId == 2)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_PSN_BATTLER2;
2017-10-18 23:05:14 +02:00
else
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_PSN_BATTLER3;
2017-10-18 23:05:14 +02:00
break;
2018-06-19 00:43:15 +02:00
case HEALTHBOX_GFX_STATUS_PRZ_BATTLER0:
2018-03-01 00:59:52 +01:00
if (battlerId == 0)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_PRZ_BATTLER0;
2018-03-01 00:59:52 +01:00
else if (battlerId == 1)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_PRZ_BATTLER1;
2018-03-01 00:59:52 +01:00
else if (battlerId == 2)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_PRZ_BATTLER2;
2017-10-18 23:05:14 +02:00
else
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_PRZ_BATTLER3;
2017-10-18 23:05:14 +02:00
break;
2018-06-19 00:43:15 +02:00
case HEALTHBOX_GFX_STATUS_SLP_BATTLER0:
2018-03-01 00:59:52 +01:00
if (battlerId == 0)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_SLP_BATTLER0;
2018-03-01 00:59:52 +01:00
else if (battlerId == 1)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_SLP_BATTLER1;
2018-03-01 00:59:52 +01:00
else if (battlerId == 2)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_SLP_BATTLER2;
2017-10-18 23:05:14 +02:00
else
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_SLP_BATTLER3;
2017-10-18 23:05:14 +02:00
break;
2018-06-19 00:43:15 +02:00
case HEALTHBOX_GFX_STATUS_FRZ_BATTLER0:
2018-03-01 00:59:52 +01:00
if (battlerId == 0)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_FRZ_BATTLER0;
2018-03-01 00:59:52 +01:00
else if (battlerId == 1)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_FRZ_BATTLER1;
2018-03-01 00:59:52 +01:00
else if (battlerId == 2)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_FRZ_BATTLER2;
2017-10-18 23:05:14 +02:00
else
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_FRZ_BATTLER3;
2017-10-18 23:05:14 +02:00
break;
2018-06-19 00:43:15 +02:00
case HEALTHBOX_GFX_STATUS_BRN_BATTLER0:
2018-03-01 00:59:52 +01:00
if (battlerId == 0)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_BRN_BATTLER0;
2018-03-01 00:59:52 +01:00
else if (battlerId == 1)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_BRN_BATTLER1;
2018-03-01 00:59:52 +01:00
else if (battlerId == 2)
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_BRN_BATTLER2;
2017-10-18 23:05:14 +02:00
else
2018-06-19 00:43:15 +02:00
ret = HEALTHBOX_GFX_STATUS_BRN_BATTLER3;
2017-10-18 23:05:14 +02:00
break;
}
return ret;
}
2017-10-19 15:28:41 +02:00
static void UpdateSafariBallsTextOnHealthbox(u8 healthboxSpriteId)
2017-10-18 23:05:14 +02:00
{
2017-10-19 15:28:41 +02:00
u32 windowId, spriteTileNum;
u8 *windowTileData;
2017-10-18 23:05:14 +02:00
windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(gText_SafariBalls, 0, 3, 2, &windowId);
2018-11-22 02:10:50 +01:00
spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * TILE_SIZE_4BPP;
2018-06-19 00:43:15 +02:00
TextIntoHealthboxObject((void*)(OBJ_VRAM0 + 0x40) + spriteTileNum, windowTileData, 6);
TextIntoHealthboxObject((void*)(OBJ_VRAM0 + 0x800) + spriteTileNum, windowTileData + 0xC0, 2);
2017-10-18 23:05:14 +02:00
RemoveWindowOnHealthbox(windowId);
}
2017-10-19 15:28:41 +02:00
static void UpdateLeftNoOfBallsTextOnHealthbox(u8 healthboxSpriteId)
2017-10-18 23:05:14 +02:00
{
2017-10-18 23:52:21 +02:00
u8 text[16];
2017-10-18 23:05:14 +02:00
u8 *txtPtr;
2017-10-19 15:28:41 +02:00
u32 windowId, spriteTileNum;
u8 *windowTileData;
2017-10-18 23:05:14 +02:00
txtPtr = StringCopy(text, gText_SafariBallLeft);
ConvertIntToDecimalStringN(txtPtr, gNumSafariBalls, STR_CONV_MODE_LEFT_ALIGN, 2);
2017-10-18 23:52:21 +02:00
windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, GetStringRightAlignXOffset(0, text, 0x2F), 3, 2, &windowId);
2018-11-22 02:10:50 +01:00
spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * TILE_SIZE_4BPP;
2018-06-19 00:43:15 +02:00
SafariTextIntoHealthboxObject((void*)(OBJ_VRAM0 + 0x2C0) + spriteTileNum, windowTileData, 2);
SafariTextIntoHealthboxObject((void*)(OBJ_VRAM0 + 0xA00) + spriteTileNum, windowTileData + 0x40, 4);
2017-10-18 23:52:21 +02:00
RemoveWindowOnHealthbox(windowId);
}
void UpdateHealthboxAttribute(u8 healthboxSpriteId, struct Pokemon *mon, u8 elementId)
{
2017-10-19 15:28:41 +02:00
s32 maxHp, currHp;
2018-06-19 00:43:15 +02:00
u8 battlerId = gSprites[healthboxSpriteId].hMain_Battler;
2017-10-18 23:52:21 +02:00
2018-06-19 00:43:15 +02:00
if (GetBattlerSide(gSprites[healthboxSpriteId].hMain_Battler) == B_SIDE_PLAYER)
2017-10-18 23:52:21 +02:00
{
u8 isDoubles;
if (elementId == HEALTHBOX_LEVEL || elementId == HEALTHBOX_ALL)
UpdateLvlInHealthbox(healthboxSpriteId, GetMonData(mon, MON_DATA_LEVEL));
if (elementId == HEALTHBOX_CURRENT_HP || elementId == HEALTHBOX_ALL)
2017-10-19 18:25:48 +02:00
UpdateHpTextInHealthbox(healthboxSpriteId, GetMonData(mon, MON_DATA_HP), HP_CURRENT);
2017-10-18 23:52:21 +02:00
if (elementId == HEALTHBOX_MAX_HP || elementId == HEALTHBOX_ALL)
2017-10-19 18:25:48 +02:00
UpdateHpTextInHealthbox(healthboxSpriteId, GetMonData(mon, MON_DATA_MAX_HP), HP_MAX);
2017-10-18 23:52:21 +02:00
if (elementId == HEALTHBOX_HEALTH_BAR || elementId == HEALTHBOX_ALL)
{
LoadBattleBarGfx(0);
maxHp = GetMonData(mon, MON_DATA_MAX_HP);
currHp = GetMonData(mon, MON_DATA_HP);
2018-03-01 00:59:52 +01:00
SetBattleBarStruct(battlerId, healthboxSpriteId, maxHp, currHp, 0);
2018-06-19 00:43:15 +02:00
MoveBattleBar(battlerId, healthboxSpriteId, HEALTH_BAR, 0);
2017-10-18 23:52:21 +02:00
}
isDoubles = IsDoubleBattle();
if (!isDoubles && (elementId == HEALTHBOX_EXP_BAR || elementId == HEALTHBOX_ALL))
{
u16 species;
2017-10-19 15:28:41 +02:00
u32 exp, currLevelExp;
s32 currExpBarValue, maxExpBarValue;
2017-10-18 23:52:21 +02:00
u8 level;
LoadBattleBarGfx(3);
species = GetMonData(mon, MON_DATA_SPECIES);
level = GetMonData(mon, MON_DATA_LEVEL);
exp = GetMonData(mon, MON_DATA_EXP);
currLevelExp = gExperienceTables[gBaseStats[species].growthRate][level];
currExpBarValue = exp - currLevelExp;
maxExpBarValue = gExperienceTables[gBaseStats[species].growthRate][level + 1] - currLevelExp;
2018-03-01 00:59:52 +01:00
SetBattleBarStruct(battlerId, healthboxSpriteId, maxExpBarValue, currExpBarValue, isDoubles);
2018-06-19 00:43:15 +02:00
MoveBattleBar(battlerId, healthboxSpriteId, EXP_BAR, 0);
2017-10-18 23:52:21 +02:00
}
if (elementId == HEALTHBOX_NICK || elementId == HEALTHBOX_ALL)
UpdateNickInHealthbox(healthboxSpriteId, mon);
if (elementId == HEALTHBOX_STATUS_ICON || elementId == HEALTHBOX_ALL)
UpdateStatusIconInHealthbox(healthboxSpriteId);
if (elementId == HEALTHBOX_SAFARI_ALL_TEXT)
UpdateSafariBallsTextOnHealthbox(healthboxSpriteId);
if (elementId == HEALTHBOX_SAFARI_ALL_TEXT || elementId == HEALTHBOX_SAFARI_BALLS_TEXT)
UpdateLeftNoOfBallsTextOnHealthbox(healthboxSpriteId);
}
else
{
if (elementId == HEALTHBOX_LEVEL || elementId == HEALTHBOX_ALL)
UpdateLvlInHealthbox(healthboxSpriteId, GetMonData(mon, MON_DATA_LEVEL));
2018-07-29 17:19:57 +02:00
if (gBattleSpritesDataPtr->battlerData[battlerId].hpNumbersNoBars && (elementId == HEALTHBOX_CURRENT_HP || elementId == HEALTHBOX_ALL))
UpdateHpTextInHealthbox(healthboxSpriteId, GetMonData(mon, MON_DATA_HP), HP_CURRENT);
if (gBattleSpritesDataPtr->battlerData[battlerId].hpNumbersNoBars && (elementId == HEALTHBOX_MAX_HP || elementId == HEALTHBOX_ALL))
UpdateHpTextInHealthbox(healthboxSpriteId, GetMonData(mon, MON_DATA_MAX_HP), HP_MAX);
2017-10-18 23:52:21 +02:00
if (elementId == HEALTHBOX_HEALTH_BAR || elementId == HEALTHBOX_ALL)
{
LoadBattleBarGfx(0);
maxHp = GetMonData(mon, MON_DATA_MAX_HP);
currHp = GetMonData(mon, MON_DATA_HP);
2018-03-01 00:59:52 +01:00
SetBattleBarStruct(battlerId, healthboxSpriteId, maxHp, currHp, 0);
2018-06-19 00:43:15 +02:00
MoveBattleBar(battlerId, healthboxSpriteId, HEALTH_BAR, 0);
2017-10-18 23:52:21 +02:00
}
if (elementId == HEALTHBOX_NICK || elementId == HEALTHBOX_ALL)
UpdateNickInHealthbox(healthboxSpriteId, mon);
if (elementId == HEALTHBOX_STATUS_ICON || elementId == HEALTHBOX_ALL)
UpdateStatusIconInHealthbox(healthboxSpriteId);
}
2017-10-18 21:42:00 +02:00
}
2017-10-19 15:28:41 +02:00
2018-06-20 23:07:51 +02:00
#define B_EXPBAR_PIXELS 64
#define B_HEALTHBAR_PIXELS 48
2018-06-19 00:43:15 +02:00
s32 MoveBattleBar(u8 battlerId, u8 healthboxSpriteId, u8 whichBar, u8 unused)
2017-10-19 15:28:41 +02:00
{
2018-06-19 00:43:15 +02:00
s32 currentBarValue;
2017-10-19 15:28:41 +02:00
if (whichBar == HEALTH_BAR) // health bar
{
2018-06-19 00:43:15 +02:00
currentBarValue = CalcNewBarValue(gBattleSpritesDataPtr->battleBars[battlerId].maxValue,
gBattleSpritesDataPtr->battleBars[battlerId].oldValue,
2018-03-01 00:59:52 +01:00
gBattleSpritesDataPtr->battleBars[battlerId].receivedValue,
2018-06-19 00:43:15 +02:00
&gBattleSpritesDataPtr->battleBars[battlerId].currValue,
2018-06-20 23:07:51 +02:00
B_HEALTHBAR_PIXELS / 8, 1);
2017-10-19 15:28:41 +02:00
}
else // exp bar
{
2018-06-19 00:43:15 +02:00
u16 expFraction = GetScaledExpFraction(gBattleSpritesDataPtr->battleBars[battlerId].oldValue,
2018-03-01 00:59:52 +01:00
gBattleSpritesDataPtr->battleBars[battlerId].receivedValue,
gBattleSpritesDataPtr->battleBars[battlerId].maxValue, 8);
2017-10-19 15:28:41 +02:00
if (expFraction == 0)
expFraction = 1;
2018-03-01 00:59:52 +01:00
expFraction = abs(gBattleSpritesDataPtr->battleBars[battlerId].receivedValue / expFraction);
2017-10-19 15:28:41 +02:00
2018-06-19 00:43:15 +02:00
currentBarValue = CalcNewBarValue(gBattleSpritesDataPtr->battleBars[battlerId].maxValue,
gBattleSpritesDataPtr->battleBars[battlerId].oldValue,
2018-03-01 00:59:52 +01:00
gBattleSpritesDataPtr->battleBars[battlerId].receivedValue,
2018-06-19 00:43:15 +02:00
&gBattleSpritesDataPtr->battleBars[battlerId].currValue,
2018-06-20 23:07:51 +02:00
B_EXPBAR_PIXELS / 8, expFraction);
2017-10-19 15:28:41 +02:00
}
2018-03-01 00:59:52 +01:00
if (whichBar == EXP_BAR || (whichBar == HEALTH_BAR && !gBattleSpritesDataPtr->battlerData[battlerId].hpNumbersNoBars))
2018-06-19 00:43:15 +02:00
MoveBattleBarGraphically(battlerId, whichBar);
2017-10-19 15:28:41 +02:00
2018-06-19 00:43:15 +02:00
if (currentBarValue == -1)
gBattleSpritesDataPtr->battleBars[battlerId].currValue = 0;
2017-10-19 15:28:41 +02:00
2018-06-19 00:43:15 +02:00
return currentBarValue;
2017-10-19 15:28:41 +02:00
}
2018-06-19 00:43:15 +02:00
static void MoveBattleBarGraphically(u8 battlerId, u8 whichBar)
2017-10-19 15:28:41 +02:00
{
2017-10-22 18:43:15 +02:00
u8 array[8];
2018-06-19 00:43:15 +02:00
u8 filledPixelsCount, level;
2017-10-19 15:28:41 +02:00
u8 barElementId;
u8 i;
switch (whichBar)
{
case HEALTH_BAR:
2018-06-19 00:43:15 +02:00
filledPixelsCount = CalcBarFilledPixels(gBattleSpritesDataPtr->battleBars[battlerId].maxValue,
gBattleSpritesDataPtr->battleBars[battlerId].oldValue,
2018-03-01 00:59:52 +01:00
gBattleSpritesDataPtr->battleBars[battlerId].receivedValue,
2018-06-19 00:43:15 +02:00
&gBattleSpritesDataPtr->battleBars[battlerId].currValue,
2018-06-20 23:07:51 +02:00
array, B_HEALTHBAR_PIXELS / 8);
2018-06-19 00:43:15 +02:00
2018-06-20 23:07:51 +02:00
if (filledPixelsCount > (B_HEALTHBAR_PIXELS * 50 / 100)) // more than 50 % hp
2018-06-19 00:43:15 +02:00
barElementId = HEALTHBOX_GFX_HP_BAR_GREEN;
2018-06-20 23:07:51 +02:00
else if (filledPixelsCount > (B_HEALTHBAR_PIXELS * 20 / 100)) // more than 20% hp
2018-06-19 00:43:15 +02:00
barElementId = HEALTHBOX_GFX_HP_BAR_YELLOW;
else
barElementId = HEALTHBOX_GFX_HP_BAR_RED; // 20 % or less
2017-10-19 15:28:41 +02:00
for (i = 0; i < 6; i++)
{
2018-06-19 00:43:15 +02:00
u8 healthbarSpriteId = gSprites[gBattleSpritesDataPtr->battleBars[battlerId].healthboxSpriteId].hMain_HealthBarSpriteId;
2017-10-19 15:28:41 +02:00
if (i < 2)
CpuCopy32(GetHealthboxElementGfxPtr(barElementId) + array[i] * 32,
2018-11-22 02:10:50 +01:00
(void*)(OBJ_VRAM0 + (gSprites[healthbarSpriteId].oam.tileNum + 2 + i) * TILE_SIZE_4BPP), 32);
2017-10-19 15:28:41 +02:00
else
CpuCopy32(GetHealthboxElementGfxPtr(barElementId) + array[i] * 32,
2018-11-22 02:10:50 +01:00
(void*)(OBJ_VRAM0 + 64 + (i + gSprites[healthbarSpriteId].oam.tileNum) * TILE_SIZE_4BPP), 32);
2017-10-19 15:28:41 +02:00
}
break;
case EXP_BAR:
2018-06-19 00:43:15 +02:00
CalcBarFilledPixels(gBattleSpritesDataPtr->battleBars[battlerId].maxValue,
gBattleSpritesDataPtr->battleBars[battlerId].oldValue,
2018-03-01 00:59:52 +01:00
gBattleSpritesDataPtr->battleBars[battlerId].receivedValue,
2018-06-19 00:43:15 +02:00
&gBattleSpritesDataPtr->battleBars[battlerId].currValue,
2018-06-20 23:07:51 +02:00
array, B_EXPBAR_PIXELS / 8);
2018-03-01 00:59:52 +01:00
level = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_LEVEL);
2018-10-17 04:47:08 +02:00
if (level == MAX_LEVEL)
2017-10-19 15:28:41 +02:00
{
for (i = 0; i < 8; i++)
array[i] = 0;
}
for (i = 0; i < 8; i++)
{
if (i < 4)
2017-10-19 18:25:48 +02:00
CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_12) + array[i] * 32,
2018-11-22 02:10:50 +01:00
(void*)(OBJ_VRAM0 + (gSprites[gBattleSpritesDataPtr->battleBars[battlerId].healthboxSpriteId].oam.tileNum + 0x24 + i) * TILE_SIZE_4BPP), 32);
2017-10-19 15:28:41 +02:00
else
2017-10-19 18:25:48 +02:00
CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_12) + array[i] * 32,
2018-11-22 02:10:50 +01:00
(void*)(OBJ_VRAM0 + 0xB80 + (i + gSprites[gBattleSpritesDataPtr->battleBars[battlerId].healthboxSpriteId].oam.tileNum) * TILE_SIZE_4BPP), 32);
2017-10-19 15:28:41 +02:00
}
break;
}
}
2018-06-19 00:43:15 +02:00
static s32 CalcNewBarValue(s32 maxValue, s32 oldValue, s32 receivedValue, s32 *currValue, u8 scale, u16 toAdd)
2017-10-19 15:28:41 +02:00
{
2018-06-19 00:43:15 +02:00
s32 ret, newValue;
scale *= 8;
2017-10-19 15:28:41 +02:00
2018-06-19 00:43:15 +02:00
if (*currValue == -32768) // first function call
2017-10-19 15:28:41 +02:00
{
2018-06-19 00:43:15 +02:00
if (maxValue < scale)
2018-06-20 23:07:51 +02:00
*currValue = Q_24_8(oldValue);
2017-10-19 15:28:41 +02:00
else
2018-06-19 00:43:15 +02:00
*currValue = oldValue;
2017-10-19 15:28:41 +02:00
}
2018-06-19 00:43:15 +02:00
newValue = oldValue - receivedValue;
if (newValue < 0)
newValue = 0;
else if (newValue > maxValue)
newValue = maxValue;
2017-10-19 15:28:41 +02:00
2018-06-19 00:43:15 +02:00
if (maxValue < scale)
2017-10-19 15:28:41 +02:00
{
2018-06-20 23:07:51 +02:00
if (newValue == Q_24_8_TO_INT(*currValue) && (*currValue & 0xFF) == 0)
2017-10-19 15:28:41 +02:00
return -1;
}
else
{
2018-06-19 00:43:15 +02:00
if (newValue == *currValue) // we're done, the bar's value has been updated
2017-10-19 15:28:41 +02:00
return -1;
}
2018-06-19 00:43:15 +02:00
if (maxValue < scale) // handle cases of max var having less pixels than the whole bar
2017-10-19 15:28:41 +02:00
{
2018-06-20 23:07:51 +02:00
s32 toAdd = Q_24_8(maxValue) / scale;
2017-10-19 15:28:41 +02:00
2018-06-19 00:43:15 +02:00
if (receivedValue < 0) // fill bar right
2017-10-19 15:28:41 +02:00
{
2018-06-20 23:07:51 +02:00
*currValue += toAdd;
ret = Q_24_8_TO_INT(*currValue);
2018-06-19 00:43:15 +02:00
if (ret >= newValue)
2017-10-19 15:28:41 +02:00
{
2018-06-20 23:07:51 +02:00
*currValue = Q_24_8(newValue);
2018-06-19 00:43:15 +02:00
ret = newValue;
2017-10-19 15:28:41 +02:00
}
}
2018-06-19 00:43:15 +02:00
else // move bar left
2017-10-19 15:28:41 +02:00
{
2018-06-20 23:07:51 +02:00
*currValue -= toAdd;
ret = Q_24_8_TO_INT(*currValue);
// try round up
2018-06-19 00:43:15 +02:00
if ((*currValue & 0xFF) > 0)
2017-10-19 15:28:41 +02:00
ret++;
2018-06-19 00:43:15 +02:00
if (ret <= newValue)
2017-10-19 15:28:41 +02:00
{
2018-06-20 23:07:51 +02:00
*currValue = Q_24_8(newValue);
2018-06-19 00:43:15 +02:00
ret = newValue;
2017-10-19 15:28:41 +02:00
}
}
}
else
{
2018-06-19 00:43:15 +02:00
if (receivedValue < 0) // fill bar right
2017-10-19 15:28:41 +02:00
{
2018-06-19 00:43:15 +02:00
*currValue += toAdd;
if (*currValue > newValue)
*currValue = newValue;
ret = *currValue;
2017-10-19 15:28:41 +02:00
}
2018-06-19 00:43:15 +02:00
else // move bar left
2017-10-19 15:28:41 +02:00
{
2018-06-19 00:43:15 +02:00
*currValue -= toAdd;
if (*currValue < newValue)
*currValue = newValue;
ret = *currValue;
2017-10-19 15:28:41 +02:00
}
}
return ret;
}
2018-06-19 00:43:15 +02:00
static u8 CalcBarFilledPixels(s32 maxValue, s32 oldValue, s32 receivedValue, s32 *currValue, u8 *arg4, u8 scale)
2017-10-19 15:28:41 +02:00
{
2018-06-19 00:43:15 +02:00
u8 pixels, filledPixels, totalPixels;
2017-10-19 15:28:41 +02:00
u8 i;
2018-06-19 00:43:15 +02:00
s32 newValue = oldValue - receivedValue;
if (newValue < 0)
newValue = 0;
else if (newValue > maxValue)
newValue = maxValue;
2017-10-19 15:28:41 +02:00
2018-06-19 00:43:15 +02:00
totalPixels = scale * 8;
2017-10-19 15:28:41 +02:00
2018-06-19 00:43:15 +02:00
for (i = 0; i < scale; i++)
2017-10-19 15:28:41 +02:00
arg4[i] = 0;
2018-06-19 00:43:15 +02:00
if (maxValue < totalPixels)
pixels = (*currValue * totalPixels / maxValue) >> 8;
2017-10-19 15:28:41 +02:00
else
2018-06-19 00:43:15 +02:00
pixels = *currValue * totalPixels / maxValue;
2017-10-19 15:28:41 +02:00
2018-06-19 00:43:15 +02:00
filledPixels = pixels;
2017-10-19 15:28:41 +02:00
2018-06-19 00:43:15 +02:00
if (filledPixels == 0 && newValue > 0)
2017-10-19 15:28:41 +02:00
{
arg4[0] = 1;
2018-06-19 00:43:15 +02:00
filledPixels = 1;
2017-10-19 15:28:41 +02:00
}
else
{
2018-06-19 00:43:15 +02:00
for (i = 0; i < scale; i++)
2017-10-19 15:28:41 +02:00
{
2018-06-19 00:43:15 +02:00
if (pixels >= 8)
2017-10-19 15:28:41 +02:00
{
arg4[i] = 8;
}
else
{
2018-06-19 00:43:15 +02:00
arg4[i] = pixels;
2017-10-19 15:28:41 +02:00
break;
}
2018-06-19 00:43:15 +02:00
pixels -= 8;
2017-10-19 15:28:41 +02:00
}
}
2018-06-19 00:43:15 +02:00
return filledPixels;
2017-10-19 15:28:41 +02:00
}
2018-06-19 00:43:15 +02:00
static u8 GetScaledExpFraction(s32 oldValue, s32 receivedValue, s32 maxValue, u8 scale)
2017-10-19 15:28:41 +02:00
{
2018-06-19 00:43:15 +02:00
s32 newVal, result;
s8 oldToMax, newToMax;
2017-10-19 15:28:41 +02:00
scale *= 8;
2018-06-19 00:43:15 +02:00
newVal = oldValue - receivedValue;
2017-10-19 15:28:41 +02:00
2018-06-19 00:43:15 +02:00
if (newVal < 0)
newVal = 0;
else if (newVal > maxValue)
newVal = maxValue;
2017-10-19 15:28:41 +02:00
2018-06-19 00:43:15 +02:00
oldToMax = oldValue * scale / maxValue;
newToMax = newVal * scale / maxValue;
result = oldToMax - newToMax;
2017-10-19 15:28:41 +02:00
return abs(result);
}
u8 GetScaledHPFraction(s16 hp, s16 maxhp, u8 scale)
{
u8 result = hp * scale / maxhp;
if (result == 0 && hp > 0)
return 1;
return result;
}
u8 GetHPBarLevel(s16 hp, s16 maxhp)
{
2018-06-20 23:07:51 +02:00
u8 result;
2017-10-19 15:28:41 +02:00
if (hp == maxhp)
{
2017-11-04 16:11:13 +01:00
result = HP_BAR_FULL;
2017-10-19 15:28:41 +02:00
}
else
{
2018-06-20 23:07:51 +02:00
u8 fraction = GetScaledHPFraction(hp, maxhp, B_HEALTHBAR_PIXELS);
if (fraction > (B_HEALTHBAR_PIXELS * 50 / 100)) // more than 50 % hp
2017-11-04 16:11:13 +01:00
result = HP_BAR_GREEN;
2018-06-20 23:07:51 +02:00
else if (fraction > (B_HEALTHBAR_PIXELS * 20 / 100)) // more than 20% hp
2017-11-04 16:11:13 +01:00
result = HP_BAR_YELLOW;
2017-10-19 15:28:41 +02:00
else if (fraction > 0)
2017-11-04 16:11:13 +01:00
result = HP_BAR_RED;
2017-10-19 15:28:41 +02:00
else
2017-11-04 16:11:13 +01:00
result = HP_BAR_EMPTY;
2017-10-19 15:28:41 +02:00
}
return result;
}
2018-11-22 02:10:50 +01:00
static u8* AddTextPrinterAndCreateWindowOnHealthbox(const u8 *str, u32 x, u32 y, u32 bgColor, u32 *windowId)
2017-10-19 15:28:41 +02:00
{
u16 winId;
2018-02-07 03:37:54 +01:00
u8 color[3];
2017-10-19 15:28:41 +02:00
struct WindowTemplate winTemplate = sHealthboxWindowTemplate;
winId = AddWindow(&winTemplate);
FillWindowPixelBuffer(winId, PIXEL_FILL(bgColor));
2017-10-19 15:28:41 +02:00
2018-11-22 02:10:50 +01:00
color[0] = bgColor;
2018-02-07 03:37:54 +01:00
color[1] = 1;
color[2] = 3;
2017-10-19 15:28:41 +02:00
AddTextPrinterParameterized4(winId, 0, x, y, 0, 0, color, -1, str);
2017-10-19 15:28:41 +02:00
*windowId = winId;
return (u8*)(GetWindowAttribute(winId, WINDOW_TILE_DATA));
}
static void RemoveWindowOnHealthbox(u32 windowId)
{
RemoveWindow(windowId);
}
2018-06-19 00:43:15 +02:00
static void FillHealthboxObject(void *dest, u32 arg1, u32 arg2)
2017-10-19 15:28:41 +02:00
{
2018-11-22 02:10:50 +01:00
CpuFill32(0x11111111 * arg1, dest, arg2 * TILE_SIZE_4BPP);
2017-10-19 15:28:41 +02:00
}
2018-11-22 02:10:50 +01:00
static void HpTextIntoHealthboxObject(void *dest, u8 *windowTileData, u32 windowWidth)
2017-10-19 15:28:41 +02:00
{
2018-11-22 02:10:50 +01:00
CpuCopy32(windowTileData + 256, dest, windowWidth * TILE_SIZE_4BPP);
2017-10-19 15:28:41 +02:00
}
2018-11-22 02:10:50 +01:00
static void TextIntoHealthboxObject(void *dest, u8 *windowTileData, s32 windowWidth)
2017-10-19 15:28:41 +02:00
{
2018-11-22 02:10:50 +01:00
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)
2017-10-19 15:28:41 +02:00
{
do
{
CpuCopy32(windowTileData + 20, dest + 20, 12);
2018-06-19 00:43:15 +02:00
dest += 32, windowTileData += 32;
2018-11-22 02:10:50 +01:00
windowWidth--;
} while (windowWidth != 0);
2017-10-19 15:28:41 +02:00
}
}
2018-11-22 02:10:50 +01:00
static void SafariTextIntoHealthboxObject(void *dest, u8 *windowTileData, u32 windowWidth)
2017-10-19 15:28:41 +02:00
{
2018-11-22 02:10:50 +01:00
CpuCopy32(windowTileData, dest, windowWidth * TILE_SIZE_4BPP);
CpuCopy32(windowTileData + 256, dest + 256, windowWidth * TILE_SIZE_4BPP);
2017-10-19 15:28:41 +02:00
}
#define ABILITY_POP_UP_TAG 0xD720
2018-09-29 12:47:35 +02:00
// for sprite
#define tOriginalX data[0]
#define tHide data[1]
#define tFrames data[2]
#define tRightToLeft data[3]
#define tBattlerId data[4]
2018-09-29 13:36:33 +02:00
#define tIsMain data[5]
2018-09-29 12:47:35 +02:00
// for task
#define tSpriteId1 data[6]
#define tSpriteId2 data[7]
static const u8 sAbilityPopUpGfx[] = INCBIN_U8("graphics/battle_interface/ability_pop_up.4bpp");
static const u16 sAbilityPopUpPalette[] = INCBIN_U16("graphics/battle_interface/ability_pop_up.gbapal");
static const struct SpriteSheet sSpriteSheet_AbilityPopUp =
{
sAbilityPopUpGfx, sizeof(sAbilityPopUpGfx), ABILITY_POP_UP_TAG
};
static const struct SpritePalette sSpritePalette_AbilityPopUp =
{
sAbilityPopUpPalette, ABILITY_POP_UP_TAG
};
static const struct OamData sOamData_AbilityPopUp =
{
.y = 0,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 0,
.shape = ST_OAM_H_RECTANGLE,
.x = 0,
.matrixNum = 0,
.size = 3,
.tileNum = 0,
.priority = 0,
.paletteNum = 0,
.affineParam = 0,
};
static const union AnimCmd sSpriteAnim_AbilityPopUp1[] =
{
ANIMCMD_FRAME(0, 0),
ANIMCMD_END
};
static const union AnimCmd *const sSpriteAnimTable_AbilityPopUp1[] =
{
sSpriteAnim_AbilityPopUp1
};
static const struct SpriteTemplate sSpriteTemplate_AbilityPopUp1 =
{
.tileTag = ABILITY_POP_UP_TAG,
.paletteTag = ABILITY_POP_UP_TAG,
.oam = &sOamData_AbilityPopUp,
.anims = sSpriteAnimTable_AbilityPopUp1,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2018-09-29 12:47:35 +02:00
.callback = SpriteCb_AbilityPopUp
};
static const union AnimCmd sSpriteAnim_AbilityPopUp2[] =
{
ANIMCMD_FRAME(32, 0),
ANIMCMD_END
};
static const union AnimCmd *const sSpriteAnimTable_AbilityPopUp2[] =
{
sSpriteAnim_AbilityPopUp2
};
static const struct SpriteTemplate sSpriteTemplate_AbilityPopUp2 =
{
.tileTag = ABILITY_POP_UP_TAG,
.paletteTag = ABILITY_POP_UP_TAG,
.oam = &sOamData_AbilityPopUp,
.anims = sSpriteAnimTable_AbilityPopUp2,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2018-09-29 12:47:35 +02:00
.callback = SpriteCb_AbilityPopUp
};
#define ABILITY_POP_UP_POS_X_DIFF 64
#define ABILITY_POP_UP_POS_X_SLIDE 68
2018-09-29 12:47:35 +02:00
static const s16 sAbilityPopUpCoordsDoubles[MAX_BATTLERS_COUNT][2] =
{
2018-09-29 13:36:33 +02:00
{29, 80}, // player left
2018-09-29 12:47:35 +02:00
{204, 19}, // opponent left
2018-09-29 13:36:33 +02:00
{29, 97}, // player right
2018-09-29 12:47:35 +02:00
{204, 36}, // opponent right
};
static const s16 sAbilityPopUpCoordsSingles[MAX_BATTLERS_COUNT][2] =
{
2018-09-29 12:47:35 +02:00
{29, 93}, // player
{204, 23}, // opponent
};
static u8* AddTextPrinterAndCreateWindowOnAbilityPopUp(const u8 *str, u32 x, u32 y, u32 color1, u32 color2, u32 color3, u32 *windowId)
{
u8 color[3] = {color1, color2, color3};
struct WindowTemplate winTemplate = {0};
winTemplate.width = 8;
winTemplate.height = 2;
*windowId = AddWindow(&winTemplate);
FillWindowPixelBuffer(*windowId, (color1 << 4) | (color1));
AddTextPrinterParameterized4(*windowId, 0, x, y, 0, 0, color, -1, str);
return (u8*)(GetWindowAttribute(*windowId, WINDOW_TILE_DATA));
}
2018-09-29 12:47:35 +02:00
static void TextIntoAbilityPopUp(void *dest, u8 *windowTileData, s32 arg2, bool32 arg3)
{
CpuCopy32(windowTileData + 256, dest + 256, arg2 * 32);
if (arg2 > 0)
{
do
{
2018-09-29 12:47:35 +02:00
if (arg3)
CpuCopy32(windowTileData + 16, dest + 16, 16);
else
CpuCopy32(windowTileData + 20, dest + 20, 12);
dest += 32, windowTileData += 32;
arg2--;
} while (arg2 != 0);
}
}
#define MAX_CHARS_PRINTED 12
static void PrintOnAbilityPopUp(const u8 *str, u8 *spriteTileData1, u8 *spriteTileData2, u32 x1, u32 x2, u32 y, u32 color1, u32 color2, u32 color3)
{
u32 windowId, i;
u8 *windowTileData;
u8 text1[MAX_CHARS_PRINTED + 1];
u8 text2[MAX_CHARS_PRINTED + 1];
2018-09-29 12:47:35 +02:00
for (i = 0; i < MAX_CHARS_PRINTED + 1; i++)
{
text1[i] = str[i];
if (text1[i] == EOS)
break;
}
text1[i] = EOS;
windowTileData = AddTextPrinterAndCreateWindowOnAbilityPopUp(text1, x1, y, color1, color2, color3, &windowId);
2018-09-29 12:47:35 +02:00
TextIntoAbilityPopUp(spriteTileData1, windowTileData, 8, (y == 0));
RemoveWindow(windowId);
2018-09-29 12:47:35 +02:00
if (i == MAX_CHARS_PRINTED + 1)
{
for (i = 0; i < MAX_CHARS_PRINTED; i++)
{
text2[i] = str[MAX_CHARS_PRINTED + i];
if (text2[i] == EOS)
break;
}
text2[i] = EOS;
windowTileData = AddTextPrinterAndCreateWindowOnAbilityPopUp(text2, x2, y, color1, color2, color3, &windowId);
2018-09-29 12:47:35 +02:00
TextIntoAbilityPopUp(spriteTileData2, windowTileData, 1, (y == 0));
RemoveWindow(windowId);
}
}
static void PrintBattlerOnAbilityPopUp(u8 battlerId, u8 spriteId1, u8 spriteId2)
{
PrintOnAbilityPopUp(gBattleMons[battlerId].nickname,
(void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32),
(void*)(OBJ_VRAM0) + (gSprites[spriteId2].oam.tileNum * 32),
7, 0,
2018-09-29 12:47:35 +02:00
0,
2, 7, 1);
}
static void PrintAbilityOnAbilityPopUp(u32 ability, u8 spriteId1, u8 spriteId2)
{
PrintOnAbilityPopUp(gAbilityNames[ability],
(void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32) + 256,
(void*)(OBJ_VRAM0) + (gSprites[spriteId2].oam.tileNum * 32) + 256,
7, 1,
4,
7, 9, 1);
}
2018-09-29 12:47:35 +02:00
#define PIXEL_COORDS_TO_OFFSET(x, y)( \
/*Add tiles by X*/ \
((y / 8) * 32 * 8) \
/*Add tiles by X*/ \
+ ((x / 8) * 32) \
/*Add pixels by Y*/ \
+ ((((y) - ((y / 8) * 8))) * 4) \
/*Add pixels by X*/ \
+ ((((x) - ((x / 8) * 8)) / 2)))
static const u16 sOverwrittenPixelsTable[][2] =
{
{PIXEL_COORDS_TO_OFFSET(0, 0), 5},
{PIXEL_COORDS_TO_OFFSET(0, 1), 5},
{PIXEL_COORDS_TO_OFFSET(0, 2), 5},
{PIXEL_COORDS_TO_OFFSET(0, 3), 5},
{PIXEL_COORDS_TO_OFFSET(0, 4), 5},
{PIXEL_COORDS_TO_OFFSET(0, 5), 5},
{PIXEL_COORDS_TO_OFFSET(0, 6), 5},
{PIXEL_COORDS_TO_OFFSET(0, 7), 3},
{PIXEL_COORDS_TO_OFFSET(0, 8), 3},
{PIXEL_COORDS_TO_OFFSET(0, 9), 3},
{PIXEL_COORDS_TO_OFFSET(0, 10), 3},
{PIXEL_COORDS_TO_OFFSET(0, 11), 3},
{PIXEL_COORDS_TO_OFFSET(0, 12), 3},
{PIXEL_COORDS_TO_OFFSET(0, 13), 8},
{PIXEL_COORDS_TO_OFFSET(8, 13), 8},
{PIXEL_COORDS_TO_OFFSET(16, 13), 8},
{PIXEL_COORDS_TO_OFFSET(24, 13), 8},
{PIXEL_COORDS_TO_OFFSET(32, 13), 8},
{PIXEL_COORDS_TO_OFFSET(40, 13), 8},
{PIXEL_COORDS_TO_OFFSET(48, 13), 8},
{PIXEL_COORDS_TO_OFFSET(56, 13), 8},
{PIXEL_COORDS_TO_OFFSET(0, 14), 8},
{PIXEL_COORDS_TO_OFFSET(8, 14), 8},
{PIXEL_COORDS_TO_OFFSET(16, 14), 8},
{PIXEL_COORDS_TO_OFFSET(24, 14), 8},
{PIXEL_COORDS_TO_OFFSET(32, 14), 8},
{PIXEL_COORDS_TO_OFFSET(40, 14), 8},
{PIXEL_COORDS_TO_OFFSET(48, 14), 8},
{PIXEL_COORDS_TO_OFFSET(56, 14), 8},
{PIXEL_COORDS_TO_OFFSET(0, 15), 3},
{PIXEL_COORDS_TO_OFFSET(0, 16), 3},
{PIXEL_COORDS_TO_OFFSET(0, 17), 3},
{PIXEL_COORDS_TO_OFFSET(0, 18), 3},
{PIXEL_COORDS_TO_OFFSET(0, 19), 3},
{PIXEL_COORDS_TO_OFFSET(0, 20), 3},
{PIXEL_COORDS_TO_OFFSET(0, 21), 3},
{PIXEL_COORDS_TO_OFFSET(0, 22), 3},
{PIXEL_COORDS_TO_OFFSET(0, 23), 3},
{PIXEL_COORDS_TO_OFFSET(0, 24), 3},
{PIXEL_COORDS_TO_OFFSET(0, 25), 3},
{PIXEL_COORDS_TO_OFFSET(0, 26), 3},
};
static inline void CopyPixels(u8 *dest, const u8 *src, u32 pixelCount)
{
2018-09-29 12:47:35 +02:00
u32 i = 0;
2018-09-29 12:47:35 +02:00
if (pixelCount & 1)
{
while (pixelCount != 0)
{
dest[i] &= ~(0xF);
dest[i] |= (src[i] & 0xF);
if (--pixelCount != 0)
{
dest[i] &= ~(0xF0);
dest[i] |= (src[i] & 0xF0);
pixelCount--;
}
i++;
}
}
else
{
for (i = 0; i < pixelCount / 2; i++)
dest[i] = src[i];
}
}
2018-09-29 12:47:35 +02:00
static void RestoreOverwrittenPixels(u8 *tiles)
{
u32 i;
u8 *buffer = Alloc(sizeof(sAbilityPopUpGfx) * 2);
2018-09-29 12:47:35 +02:00
CpuCopy32(tiles, buffer, sizeof(sAbilityPopUpGfx));
for (i = 0; i < ARRAY_COUNT(sOverwrittenPixelsTable); i++)
{
CopyPixels(buffer + sOverwrittenPixelsTable[i][0],
sAbilityPopUpGfx + sOverwrittenPixelsTable[i][0],
sOverwrittenPixelsTable[i][1]);
}
CpuCopy32(buffer, tiles, sizeof(sAbilityPopUpGfx));
Free(buffer);
}
void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle)
{
const s16 (*coords)[2];
u8 spriteId1, spriteId2, battlerPosition, taskId;
2018-11-03 10:51:51 +01:00
if (B_ABILITY_POP_UP < GEN_5)
return;
2018-09-29 12:47:35 +02:00
if (!gBattleStruct->activeAbilityPopUps)
{
LoadSpriteSheet(&sSpriteSheet_AbilityPopUp);
LoadSpritePalette(&sSpritePalette_AbilityPopUp);
}
gBattleStruct->activeAbilityPopUps |= gBitTable[battlerId];
battlerPosition = GetBattlerPosition(battlerId);
if (isDoubleBattle)
coords = sAbilityPopUpCoordsDoubles;
else
coords = sAbilityPopUpCoordsSingles;
if ((battlerPosition & BIT_SIDE) == B_SIDE_PLAYER)
{
spriteId1 = CreateSprite(&sSpriteTemplate_AbilityPopUp1,
coords[battlerPosition][0] - ABILITY_POP_UP_POS_X_SLIDE,
coords[battlerPosition][1], 0);
spriteId2 = CreateSprite(&sSpriteTemplate_AbilityPopUp2,
coords[battlerPosition][0] - ABILITY_POP_UP_POS_X_SLIDE + ABILITY_POP_UP_POS_X_DIFF,
coords[battlerPosition][1], 0);
gSprites[spriteId1].tOriginalX = coords[battlerPosition][0];
gSprites[spriteId2].tOriginalX = coords[battlerPosition][0] + ABILITY_POP_UP_POS_X_DIFF;
gSprites[spriteId1].tRightToLeft = TRUE;
gSprites[spriteId2].tRightToLeft = TRUE;
}
else
{
spriteId1 = CreateSprite(&sSpriteTemplate_AbilityPopUp1,
coords[battlerPosition][0] + ABILITY_POP_UP_POS_X_SLIDE,
coords[battlerPosition][1], 0);
spriteId2 = CreateSprite(&sSpriteTemplate_AbilityPopUp2,
coords[battlerPosition][0] + ABILITY_POP_UP_POS_X_SLIDE + ABILITY_POP_UP_POS_X_DIFF,
coords[battlerPosition][1], 0);
gSprites[spriteId1].tOriginalX = coords[battlerPosition][0];
gSprites[spriteId2].tOriginalX = coords[battlerPosition][0] + ABILITY_POP_UP_POS_X_DIFF;
gSprites[spriteId1].tRightToLeft = FALSE;
gSprites[spriteId2].tRightToLeft = FALSE;
}
taskId = CreateTask(Task_FreeAbilityPopUpGfx, 5);
gTasks[taskId].tSpriteId1 = spriteId1;
gTasks[taskId].tSpriteId2 = spriteId2;
2018-09-29 13:36:33 +02:00
gSprites[spriteId1].tIsMain = TRUE;
gSprites[spriteId1].tBattlerId = battlerId;
gSprites[spriteId2].tBattlerId = battlerId;
2018-09-29 12:47:35 +02:00
StartSpriteAnim(&gSprites[spriteId1], 0);
StartSpriteAnim(&gSprites[spriteId2], 0);
PrintBattlerOnAbilityPopUp(battlerId, spriteId1, spriteId2);
PrintAbilityOnAbilityPopUp(ability, spriteId1, spriteId2);
2018-09-29 12:47:35 +02:00
RestoreOverwrittenPixels((void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32));
}
2018-09-29 12:47:35 +02:00
#define FRAMES_TO_WAIT 48
static void SpriteCb_AbilityPopUp(struct Sprite *sprite)
{
if (!sprite->tHide) // Show
{
2018-09-29 13:36:33 +02:00
if (sprite->tIsMain && ++sprite->tFrames == 4)
PlaySE(SE_SELECT);
2018-09-29 15:43:56 +02:00
if ((!sprite->tRightToLeft && (sprite->pos1.x -= 4) <= sprite->tOriginalX)
|| (sprite->tRightToLeft && (sprite->pos1.x += 4) >= sprite->tOriginalX)
2018-09-29 12:47:35 +02:00
)
{
2018-09-29 12:47:35 +02:00
sprite->pos1.x = sprite->tOriginalX;
sprite->tHide = TRUE;
2018-09-29 12:47:35 +02:00
sprite->tFrames = FRAMES_TO_WAIT;
}
}
else // Hide
{
if (sprite->tFrames == 0)
{
2018-09-29 15:43:56 +02:00
if ((!sprite->tRightToLeft && (sprite->pos1.x += 4) >= sprite->tOriginalX + ABILITY_POP_UP_POS_X_SLIDE)
||(sprite->tRightToLeft && (sprite->pos1.x -= 4) <= sprite->tOriginalX - ABILITY_POP_UP_POS_X_SLIDE)
2018-09-29 12:47:35 +02:00
)
{
2018-09-29 12:47:35 +02:00
gBattleStruct->activeAbilityPopUps &= ~(gBitTable[sprite->tBattlerId]);
DestroySprite(sprite);
}
}
else
{
sprite->tFrames--;
}
}
}
2018-09-29 12:47:35 +02:00
static void Task_FreeAbilityPopUpGfx(u8 taskId)
{
2018-09-29 12:47:35 +02:00
if (!gSprites[gTasks[taskId].tSpriteId1].inUse
&& !gSprites[gTasks[taskId].tSpriteId2].inUse
&& !gBattleStruct->activeAbilityPopUps)
{
2018-09-29 12:47:35 +02:00
FreeSpriteTilesByTag(ABILITY_POP_UP_TAG);
FreeSpritePaletteByTag(ABILITY_POP_UP_TAG);
DestroyTask(taskId);
}
}