pokeemerald/src/battle_gfx_sfx_util.c

1299 lines
44 KiB
C
Raw Normal View History

2017-11-04 16:11:13 +01:00
#include "global.h"
#include "battle.h"
#include "battle_controllers.h"
#include "battle_ai_script_commands.h"
#include "battle_anim.h"
2017-12-31 16:28:57 +01:00
#include "constants/battle_anim.h"
2017-11-04 16:11:13 +01:00
#include "battle_interface.h"
#include "main.h"
#include "malloc.h"
2018-10-21 09:24:57 +02:00
#include "graphics.h"
#include "random.h"
2017-11-04 16:11:13 +01:00
#include "util.h"
#include "pokemon.h"
2017-12-11 19:27:51 +01:00
#include "constants/moves.h"
2017-11-04 16:11:13 +01:00
#include "task.h"
#include "sprite.h"
#include "sound.h"
2018-12-24 00:02:29 +01:00
#include "party_menu.h"
2017-11-04 16:11:13 +01:00
#include "m4a.h"
2017-12-11 19:27:51 +01:00
#include "constants/species.h"
2017-11-04 16:11:13 +01:00
#include "decompress.h"
2019-04-04 23:53:06 +02:00
#include "data.h"
2017-11-04 16:11:13 +01:00
#include "palette.h"
#include "contest.h"
2017-12-11 19:27:51 +01:00
#include "constants/songs.h"
2018-02-08 12:13:29 +01:00
#include "constants/rgb.h"
2020-07-17 02:12:12 +02:00
#include "constants/battle_palace.h"
2017-11-04 16:11:13 +01:00
extern struct MusicPlayerInfo gMPlayInfo_SE1;
extern struct MusicPlayerInfo gMPlayInfo_SE2;
extern struct MusicPlayerInfo gMPlayInfo_BGM;
2017-11-04 16:11:13 +01:00
2020-07-17 02:12:12 +02:00
extern const u8 gBattlePalaceNatureToMoveTarget[];
2018-09-12 22:58:03 +02:00
extern const u8 * const gBattleAnims_General[];
2017-12-31 16:28:57 +01:00
extern const u8 * const gBattleAnims_Special[];
2017-11-04 16:11:13 +01:00
extern const struct CompressedSpriteSheet gSpriteSheet_EnemyShadow;
extern const struct SpriteTemplate gSpriteTemplate_EnemyShadow;
// this file's functions
2020-07-17 02:12:12 +02:00
static u8 GetBattlePalaceMoveGroup(u16 move);
static u16 GetBattlePalaceTarget(void);
2017-11-04 16:11:13 +01:00
static void sub_805D7EC(struct Sprite *sprite);
static bool8 ShouldAnimBeDoneRegardlessOfSubsitute(u8 animId);
static void Task_ClearBitWhenBattleTableAnimDone(u8 taskId);
static void Task_ClearBitWhenSpecialAnimDone(u8 taskId);
2018-06-19 00:43:15 +02:00
static void ClearSpritesBattlerHealthboxAnimData(void);
2017-11-04 16:11:13 +01:00
// const rom data
2018-07-01 11:15:42 +02:00
static const struct CompressedSpriteSheet sSpriteSheet_SinglesPlayerHealthbox =
2017-11-04 16:11:13 +01:00
{
2018-09-20 21:42:38 +02:00
gHealthboxSinglesPlayerGfx, 0x1000, TAG_HEALTHBOX_PLAYER1_TILE
2017-11-04 16:11:13 +01:00
};
2018-07-01 11:15:42 +02:00
static const struct CompressedSpriteSheet sSpriteSheet_SinglesOpponentHealthbox =
2017-11-04 16:11:13 +01:00
{
2018-09-20 21:42:38 +02:00
gHealthboxSinglesOpponentGfx, 0x1000, TAG_HEALTHBOX_OPPONENT1_TILE
2017-11-04 16:11:13 +01:00
};
2018-07-01 11:15:42 +02:00
static const struct CompressedSpriteSheet sSpriteSheets_DoublesPlayerHealthbox[2] =
2017-11-04 16:11:13 +01:00
{
2018-09-20 21:42:38 +02:00
{gHealthboxDoublesPlayerGfx, 0x800, TAG_HEALTHBOX_PLAYER1_TILE},
{gHealthboxDoublesPlayerGfx, 0x800, TAG_HEALTHBOX_PLAYER2_TILE}
2017-11-04 16:11:13 +01:00
};
2018-07-01 11:15:42 +02:00
static const struct CompressedSpriteSheet sSpriteSheets_DoublesOpponentHealthbox[2] =
2017-11-04 16:11:13 +01:00
{
2018-09-20 21:42:38 +02:00
{gHealthboxDoublesOpponentGfx, 0x800, TAG_HEALTHBOX_OPPONENT1_TILE},
{gHealthboxDoublesOpponentGfx, 0x800, TAG_HEALTHBOX_OPPONENT2_TILE}
2017-11-04 16:11:13 +01:00
};
2018-07-01 11:15:42 +02:00
static const struct CompressedSpriteSheet sSpriteSheet_SafariHealthbox =
2017-11-04 16:11:13 +01:00
{
2018-09-20 21:42:38 +02:00
gHealthboxSafariGfx, 0x1000, TAG_HEALTHBOX_SAFARI_TILE
2017-11-04 16:11:13 +01:00
};
2018-07-01 11:15:42 +02:00
static const struct CompressedSpriteSheet sSpriteSheets_HealthBar[MAX_BATTLERS_COUNT] =
2017-11-04 16:11:13 +01:00
{
2018-07-01 11:15:42 +02:00
{gBlankGfxCompressed, 0x0100, TAG_HEALTHBAR_PLAYER1_TILE},
{gBlankGfxCompressed, 0x0120, TAG_HEALTHBAR_OPPONENT1_TILE},
{gBlankGfxCompressed, 0x0100, TAG_HEALTHBAR_PLAYER2_TILE},
{gBlankGfxCompressed, 0x0120, TAG_HEALTHBAR_OPPONENT2_TILE}
2017-11-04 16:11:13 +01:00
};
2018-07-01 11:15:42 +02:00
static const struct SpritePalette sSpritePalettes_HealthBoxHealthBar[2] =
2017-11-04 16:11:13 +01:00
{
{gBattleInterface_BallStatusBarPal, TAG_HEALTHBOX_PAL},
2018-07-01 11:15:42 +02:00
{gBattleInterface_BallDisplayPal, TAG_HEALTHBAR_PAL}
2017-11-04 16:11:13 +01:00
};
// code
void AllocateBattleSpritesData(void)
{
gBattleSpritesDataPtr = AllocZeroed(sizeof(struct BattleSpriteData));
2018-02-06 23:09:39 +01:00
gBattleSpritesDataPtr->battlerData = AllocZeroed(sizeof(struct BattleSpriteInfo) * MAX_BATTLERS_COUNT);
2018-02-06 02:46:59 +01:00
gBattleSpritesDataPtr->healthBoxesData = AllocZeroed(sizeof(struct BattleHealthboxInfo) * MAX_BATTLERS_COUNT);
2017-11-04 16:11:13 +01:00
gBattleSpritesDataPtr->animationData = AllocZeroed(sizeof(struct BattleAnimationInfo));
2018-02-06 02:46:59 +01:00
gBattleSpritesDataPtr->battleBars = AllocZeroed(sizeof(struct BattleBarInfo) * MAX_BATTLERS_COUNT);
2017-11-04 16:11:13 +01:00
}
void FreeBattleSpritesData(void)
{
if (gBattleSpritesDataPtr == NULL)
return;
FREE_AND_SET_NULL(gBattleSpritesDataPtr->battleBars);
FREE_AND_SET_NULL(gBattleSpritesDataPtr->animationData);
FREE_AND_SET_NULL(gBattleSpritesDataPtr->healthBoxesData);
2018-02-06 23:09:39 +01:00
FREE_AND_SET_NULL(gBattleSpritesDataPtr->battlerData);
2017-11-04 16:11:13 +01:00
FREE_AND_SET_NULL(gBattleSpritesDataPtr);
}
2020-07-17 02:12:12 +02:00
// Pokemon chooses move to use in Battle Palace rather than player
2017-11-04 16:11:13 +01:00
u16 ChooseMoveAndTargetInBattlePalace(void)
{
s32 i, var1, var2;
s32 chosenMoveId = -1;
2018-02-06 02:46:59 +01:00
struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleBufferA[gActiveBattler][4]);
u8 unusableMovesBits = CheckMoveLimitations(gActiveBattler, 0, 0xFF);
2017-11-04 16:11:13 +01:00
s32 percent = Random() % 100;
2020-07-17 02:12:12 +02:00
// Heavy variable re-use here makes this hard to read without defines
// Possibly just optimization? might still match with additional vars
#define maxGroupNum var1
#define minGroupNum var2
#define selectedGroup percent
#define selectedMoves var2
#define moveTarget var1
#define validMoveFlags var1
#define numValidMoveGroups var2
#define validMoveGroup var2
// If battler is < 50% HP and not asleep, use second set of move group likelihoods
// otherwise use first set
i = (gBattleStruct->palaceFlags & gBitTable[gActiveBattler]) ? 2 : 0;
minGroupNum = i;
maxGroupNum = i + 2; // + 2 because there are two percentages per set of likelihoods
// Each nature has a different percent chance to select a move from one of 3 move groups
// If percent is less than 1st check, use move from "Attack" group
// If percent is less than 2nd check, use move from "Defense" group
// Otherwise use move from "Support" group
for (; i < maxGroupNum; i++)
2017-11-04 16:11:13 +01:00
{
2020-07-17 02:12:12 +02:00
if (gBattlePalaceNatureToMoveGroupLikelihood[GetNatureFromPersonality(gBattleMons[gActiveBattler].personality)][i] > percent)
2017-11-04 16:11:13 +01:00
break;
}
2020-07-17 02:12:12 +02:00
selectedGroup = i - minGroupNum;
if (i == maxGroupNum)
selectedGroup = PALACE_MOVE_GROUP_SUPPORT;
2017-11-04 16:11:13 +01:00
2020-07-17 02:12:12 +02:00
// Flag moves that match selected group, to be passed to AI
for (selectedMoves = 0, i = 0; i < MAX_MON_MOVES; i++)
2017-11-04 16:11:13 +01:00
{
if (moveInfo->moves[i] == MOVE_NONE)
break;
2020-07-17 02:12:12 +02:00
if (selectedGroup == GetBattlePalaceMoveGroup(moveInfo->moves[i]) && moveInfo->currentPp[i] != 0)
selectedMoves |= gBitTable[i];
2017-11-04 16:11:13 +01:00
}
2020-07-17 02:12:12 +02:00
// Pass selected moves to AI, pick one
if (selectedMoves != 0)
2017-11-04 16:11:13 +01:00
{
2020-07-17 02:12:12 +02:00
gBattleStruct->palaceFlags &= 0xF;
gBattleStruct->palaceFlags |= (selectedMoves << 4);
BattleAI_SetupAIData(selectedMoves);
2017-11-04 16:11:13 +01:00
chosenMoveId = BattleAI_ChooseMoveOrAction();
}
2020-07-17 02:12:12 +02:00
// If no moves matched the selected group, pick a new move from groups the pokemon has
// In this case the AI is not checked again, so the choice may be worse
// If a move is chosen this way, there's a 50% chance that it will be unable to use it anyway
2017-11-04 16:11:13 +01:00
if (chosenMoveId == -1)
{
if (unusableMovesBits != 0xF)
{
2020-07-17 02:12:12 +02:00
validMoveFlags = 0, numValidMoveGroups = 0;
2017-11-04 16:11:13 +01:00
for (i = 0; i < MAX_MON_MOVES; i++)
2017-11-04 16:11:13 +01:00
{
2020-07-17 02:12:12 +02:00
// validMoveFlags is used here as a bitfield for which moves can be used for each move group type
// first 4 bits are for attack (1 for each move), then 4 bits for defense, and 4 for support
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_ATTACK && !(gBitTable[i] & unusableMovesBits))
validMoveFlags += (1 << 0);
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_DEFENSE && !(gBitTable[i] & unusableMovesBits))
validMoveFlags += (1 << 4);
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_SUPPORT && !(gBitTable[i] & unusableMovesBits))
validMoveFlags += (1 << 8);
2017-11-04 16:11:13 +01:00
}
2020-07-17 02:12:12 +02:00
// Count the move groups the pokemon has
if ((validMoveFlags & 0xF) > 1)
numValidMoveGroups++;
if ((validMoveFlags & 0xF0) > 0x1F)
numValidMoveGroups++;
if ((validMoveFlags & 0xF0) > 0x1FF)
numValidMoveGroups++;
// If more than 1 possible move group, or no possible move groups
// then choose move randomly
if (numValidMoveGroups > 1 || numValidMoveGroups == 0)
2017-11-04 16:11:13 +01:00
{
do
{
i = Random() % MAX_MON_MOVES;
2017-11-04 16:11:13 +01:00
if (!(gBitTable[i] & unusableMovesBits))
chosenMoveId = i;
} while (chosenMoveId == -1);
}
2020-07-17 02:12:12 +02:00
// Otherwise randomly choose move of only available move group
2017-11-04 16:11:13 +01:00
else
{
2020-07-17 02:12:12 +02:00
if ((validMoveFlags & 0xF) > 1)
validMoveGroup = PALACE_MOVE_GROUP_ATTACK;
if ((validMoveFlags & 0xF0) > 0x1F)
validMoveGroup = PALACE_MOVE_GROUP_DEFENSE;
if ((validMoveFlags & 0xF0) > 0x1FF)
validMoveGroup = PALACE_MOVE_GROUP_SUPPORT;
2017-11-04 16:11:13 +01:00
do
{
i = Random() % MAX_MON_MOVES;
2020-07-17 02:12:12 +02:00
if (!(gBitTable[i] & unusableMovesBits) && validMoveGroup == GetBattlePalaceMoveGroup(moveInfo->moves[i]))
2017-11-04 16:11:13 +01:00
chosenMoveId = i;
} while (chosenMoveId == -1);
}
2020-07-17 02:12:12 +02:00
// If a move was selected (and in this case was not from the Nature-chosen group)
// then there's a 50% chance it won't be used anyway
2017-11-04 16:11:13 +01:00
if (Random() % 100 > 49)
{
2020-07-17 02:12:12 +02:00
gProtectStructs[gActiveBattler].palaceUnableToUseMove = TRUE;
2017-11-04 16:11:13 +01:00
return 0;
}
}
else
{
2020-07-17 02:12:12 +02:00
gProtectStructs[gActiveBattler].palaceUnableToUseMove = TRUE;
2017-11-04 16:11:13 +01:00
return 0;
}
}
if (moveInfo->moves[chosenMoveId] == MOVE_CURSE)
{
if (moveInfo->monType1 != TYPE_GHOST && moveInfo->monType2 != TYPE_GHOST)
2020-07-17 02:12:12 +02:00
moveTarget = MOVE_TARGET_USER;
2017-11-04 16:11:13 +01:00
else
2020-07-17 02:12:12 +02:00
moveTarget = MOVE_TARGET_SELECTED;
2017-11-04 16:11:13 +01:00
}
else
{
2020-07-17 02:12:12 +02:00
moveTarget = gBattleMoves[moveInfo->moves[chosenMoveId]].target;
2017-11-04 16:11:13 +01:00
}
2020-07-17 02:12:12 +02:00
if (moveTarget & MOVE_TARGET_USER)
2018-02-06 02:46:59 +01:00
chosenMoveId |= (gActiveBattler << 8);
2020-07-17 02:12:12 +02:00
else if (moveTarget == MOVE_TARGET_SELECTED)
chosenMoveId |= GetBattlePalaceTarget();
2017-11-04 16:11:13 +01:00
else
2018-02-06 02:46:59 +01:00
chosenMoveId |= (GetBattlerAtPosition((GetBattlerPosition(gActiveBattler) & BIT_SIDE) ^ BIT_SIDE) << 8);
2017-11-04 16:11:13 +01:00
return chosenMoveId;
}
2020-07-17 02:12:12 +02:00
#undef maxGroupNum
#undef minGroupNum
#undef selectedGroup
#undef selectedMoves
#undef moveTarget
#undef validMoveFlags
#undef numValidMoveGroups
#undef validMoveGroup
static u8 GetBattlePalaceMoveGroup(u16 move)
2017-11-04 16:11:13 +01:00
{
switch (gBattleMoves[move].target)
{
case MOVE_TARGET_SELECTED:
2018-02-26 13:24:46 +01:00
case MOVE_TARGET_USER_OR_SELECTED:
2017-11-04 16:11:13 +01:00
case MOVE_TARGET_RANDOM:
case MOVE_TARGET_BOTH:
case MOVE_TARGET_FOES_AND_ALLY:
if (gBattleMoves[move].power == 0)
2020-07-17 02:12:12 +02:00
return PALACE_MOVE_GROUP_SUPPORT;
2017-11-04 16:11:13 +01:00
else
2020-07-17 02:12:12 +02:00
return PALACE_MOVE_GROUP_ATTACK;
2017-11-04 16:11:13 +01:00
break;
case MOVE_TARGET_DEPENDS:
case MOVE_TARGET_OPPONENTS_FIELD:
2020-07-17 02:12:12 +02:00
return PALACE_MOVE_GROUP_SUPPORT;
2018-02-26 13:24:46 +01:00
case MOVE_TARGET_USER:
2020-07-17 02:12:12 +02:00
return PALACE_MOVE_GROUP_DEFENSE;
2017-11-04 16:11:13 +01:00
default:
2020-07-17 02:12:12 +02:00
return PALACE_MOVE_GROUP_ATTACK;
2017-11-04 16:11:13 +01:00
}
}
2020-07-17 02:12:12 +02:00
static u16 GetBattlePalaceTarget(void)
2017-11-04 16:11:13 +01:00
{
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
u8 opposing1, opposing2;
2018-02-06 02:46:59 +01:00
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
2017-11-04 16:11:13 +01:00
{
2018-02-06 02:46:59 +01:00
opposing1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
opposing2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
2017-11-04 16:11:13 +01:00
}
else
{
2018-02-06 02:46:59 +01:00
opposing1 = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
opposing2 = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
2017-11-04 16:11:13 +01:00
}
if (gBattleMons[opposing1].hp == gBattleMons[opposing2].hp)
2018-02-06 02:46:59 +01:00
return (((gActiveBattler & BIT_SIDE) ^ BIT_SIDE) + (Random() & 2)) << 8;
2017-11-04 16:11:13 +01:00
2020-07-17 02:12:12 +02:00
switch (gBattlePalaceNatureToMoveTarget[GetNatureFromPersonality(gBattleMons[gActiveBattler].personality)])
2017-11-04 16:11:13 +01:00
{
2020-07-17 02:12:12 +02:00
case PALACE_TARGET_STRONGER:
2017-11-04 16:11:13 +01:00
if (gBattleMons[opposing1].hp > gBattleMons[opposing2].hp)
return opposing1 << 8;
else
return opposing2 << 8;
2020-07-17 02:12:12 +02:00
case PALACE_TARGET_WEAKER:
2017-11-04 16:11:13 +01:00
if (gBattleMons[opposing1].hp < gBattleMons[opposing2].hp)
return opposing1 << 8;
else
return opposing2 << 8;
2020-07-17 02:12:12 +02:00
case PALACE_TARGET_RANDOM:
2018-02-06 02:46:59 +01:00
return (((gActiveBattler & BIT_SIDE) ^ BIT_SIDE) + (Random() & 2)) << 8;
2017-11-04 16:11:13 +01:00
}
}
2018-02-06 02:46:59 +01:00
return (gActiveBattler ^ BIT_SIDE) << 8;
2017-11-04 16:11:13 +01:00
}
void sub_805D714(struct Sprite *sprite)
{
2017-12-02 21:44:50 +01:00
u8 spriteId = sprite->data[1];
2017-11-04 16:11:13 +01:00
if (!gSprites[spriteId].affineAnimEnded)
return;
if (gSprites[spriteId].invisible)
return;
if (gSprites[spriteId].animPaused)
{
gSprites[spriteId].animPaused = 0;
}
else
{
if (gSprites[spriteId].animEnded)
sprite->callback = SpriteCallbackDummy;
}
}
void sub_805D770(struct Sprite *sprite, bool8 arg1)
{
sprite->animPaused = 1;
sprite->callback = SpriteCallbackDummy;
if (!arg1)
StartSpriteAffineAnim(sprite, 1);
else
StartSpriteAffineAnim(sprite, 1);
AnimateSprite(sprite);
}
void sub_805D7AC(struct Sprite *sprite)
{
2018-02-08 11:17:41 +01:00
if (!(gIntroSlideFlags & 1))
2017-11-04 16:11:13 +01:00
{
2017-12-02 21:44:50 +01:00
sprite->pos2.x += sprite->data[0];
2017-11-04 16:11:13 +01:00
if (sprite->pos2.x == 0)
{
if (sprite->pos2.y != 0)
sprite->callback = sub_805D7EC;
else
sprite->callback = SpriteCallbackDummy;
}
}
}
static void sub_805D7EC(struct Sprite *sprite)
{
sprite->pos2.y -= 2;
if (sprite->pos2.y == 0)
sprite->callback = SpriteCallbackDummy;
}
void InitAndLaunchChosenStatusAnimation(bool8 isStatus2, u32 status)
{
2018-02-06 02:46:59 +01:00
gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].statusAnimActive = 1;
2017-11-04 16:11:13 +01:00
if (!isStatus2)
{
2018-01-16 22:12:38 +01:00
if (status == STATUS1_FREEZE)
2018-02-06 02:46:59 +01:00
LaunchStatusAnimation(gActiveBattler, B_ANIM_STATUS_FRZ);
2018-01-16 22:12:38 +01:00
else if (status == STATUS1_POISON || status & STATUS1_TOXIC_POISON)
2018-02-06 02:46:59 +01:00
LaunchStatusAnimation(gActiveBattler, B_ANIM_STATUS_PSN);
2018-01-16 22:12:38 +01:00
else if (status == STATUS1_BURN)
2018-02-06 02:46:59 +01:00
LaunchStatusAnimation(gActiveBattler, B_ANIM_STATUS_BRN);
2018-01-16 22:12:38 +01:00
else if (status & STATUS1_SLEEP)
2018-02-06 02:46:59 +01:00
LaunchStatusAnimation(gActiveBattler, B_ANIM_STATUS_SLP);
2018-01-16 22:12:38 +01:00
else if (status == STATUS1_PARALYSIS)
2018-02-06 02:46:59 +01:00
LaunchStatusAnimation(gActiveBattler, B_ANIM_STATUS_PRZ);
2017-11-04 16:11:13 +01:00
else // no animation
2018-02-06 02:46:59 +01:00
gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].statusAnimActive = 0;
2017-11-04 16:11:13 +01:00
}
else
{
if (status & STATUS2_INFATUATION)
2018-02-06 02:46:59 +01:00
LaunchStatusAnimation(gActiveBattler, B_ANIM_STATUS_INFATUATION);
2017-11-04 16:11:13 +01:00
else if (status & STATUS2_CONFUSION)
2018-02-06 02:46:59 +01:00
LaunchStatusAnimation(gActiveBattler, B_ANIM_STATUS_CONFUSION);
2017-11-04 16:11:13 +01:00
else if (status & STATUS2_CURSED)
2018-02-06 02:46:59 +01:00
LaunchStatusAnimation(gActiveBattler, B_ANIM_STATUS_CURSED);
2017-11-04 16:11:13 +01:00
else if (status & STATUS2_NIGHTMARE)
2018-02-06 02:46:59 +01:00
LaunchStatusAnimation(gActiveBattler, B_ANIM_STATUS_NIGHTMARE);
2017-11-04 16:11:13 +01:00
else if (status & STATUS2_WRAPPED)
2018-02-06 02:46:59 +01:00
LaunchStatusAnimation(gActiveBattler, B_ANIM_STATUS_WRAPPED); // this animation doesn't actually exist
2017-11-04 16:11:13 +01:00
else // no animation
2018-02-06 02:46:59 +01:00
gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].statusAnimActive = 0;
2017-11-04 16:11:13 +01:00
}
}
2018-02-08 12:13:29 +01:00
#define tBattlerId data[0]
2017-11-04 16:11:13 +01:00
2018-06-19 00:43:15 +02:00
bool8 TryHandleLaunchBattleTableAnimation(u8 activeBattler, u8 atkBattler, u8 defBattler, u8 tableId, u16 argument)
2017-11-04 16:11:13 +01:00
{
u8 taskId;
if (tableId == B_ANIM_CASTFORM_CHANGE && (argument & 0x80))
{
2018-06-19 00:43:15 +02:00
gBattleMonForms[activeBattler] = (argument & ~(0x80));
2017-11-04 16:11:13 +01:00
return TRUE;
}
2018-06-19 00:43:15 +02:00
if (gBattleSpritesDataPtr->battlerData[activeBattler].behindSubstitute
2017-11-04 16:11:13 +01:00
&& !ShouldAnimBeDoneRegardlessOfSubsitute(tableId))
{
return TRUE;
}
2018-06-19 00:43:15 +02:00
if (gBattleSpritesDataPtr->battlerData[activeBattler].behindSubstitute
2017-11-04 16:11:13 +01:00
&& tableId == B_ANIM_SUBSTITUTE_FADE
2018-06-19 00:43:15 +02:00
&& gSprites[gBattlerSpriteIds[activeBattler]].invisible)
2017-11-04 16:11:13 +01:00
{
2018-06-19 00:43:15 +02:00
LoadBattleMonGfxAndAnimate(activeBattler, TRUE, gBattlerSpriteIds[activeBattler]);
ClearBehindSubstituteBit(activeBattler);
2017-11-04 16:11:13 +01:00
return TRUE;
}
2018-06-19 00:43:15 +02:00
gBattleAnimAttacker = atkBattler;
gBattleAnimTarget = defBattler;
2017-11-04 16:11:13 +01:00
gBattleSpritesDataPtr->animationData->animArg = argument;
2018-09-12 22:58:03 +02:00
LaunchBattleAnimation(gBattleAnims_General, tableId, FALSE);
2017-11-04 16:11:13 +01:00
taskId = CreateTask(Task_ClearBitWhenBattleTableAnimDone, 10);
2018-06-19 00:43:15 +02:00
gTasks[taskId].tBattlerId = activeBattler;
2018-02-08 12:13:29 +01:00
gBattleSpritesDataPtr->healthBoxesData[gTasks[taskId].tBattlerId].animFromTableActive = 1;
2017-11-04 16:11:13 +01:00
return FALSE;
}
static void Task_ClearBitWhenBattleTableAnimDone(u8 taskId)
{
gAnimScriptCallback();
if (!gAnimScriptActive)
{
2018-02-08 12:13:29 +01:00
gBattleSpritesDataPtr->healthBoxesData[gTasks[taskId].tBattlerId].animFromTableActive = 0;
2017-11-04 16:11:13 +01:00
DestroyTask(taskId);
}
}
2018-02-08 12:13:29 +01:00
#undef tBattlerId
2017-11-04 16:11:13 +01:00
static bool8 ShouldAnimBeDoneRegardlessOfSubsitute(u8 animId)
{
switch (animId)
{
case B_ANIM_SUBSTITUTE_FADE:
case B_ANIM_RAIN_CONTINUES:
case B_ANIM_SUN_CONTINUES:
case B_ANIM_SANDSTORM_CONTINUES:
case B_ANIM_HAIL_CONTINUES:
case B_ANIM_SNATCH_MOVE:
return TRUE;
default:
return FALSE;
}
}
2018-02-08 12:13:29 +01:00
#define tBattlerId data[0]
2017-11-04 16:11:13 +01:00
2018-06-19 00:43:15 +02:00
void InitAndLaunchSpecialAnimation(u8 activeBattler, u8 atkBattler, u8 defBattler, u8 tableId)
2017-11-04 16:11:13 +01:00
{
u8 taskId;
2018-06-19 00:43:15 +02:00
gBattleAnimAttacker = atkBattler;
gBattleAnimTarget = defBattler;
2017-12-31 16:28:57 +01:00
LaunchBattleAnimation(gBattleAnims_Special, tableId, FALSE);
2017-11-04 16:11:13 +01:00
taskId = CreateTask(Task_ClearBitWhenSpecialAnimDone, 10);
2018-06-19 00:43:15 +02:00
gTasks[taskId].tBattlerId = activeBattler;
2018-02-08 12:13:29 +01:00
gBattleSpritesDataPtr->healthBoxesData[gTasks[taskId].tBattlerId].specialAnimActive = 1;
2017-11-04 16:11:13 +01:00
}
static void Task_ClearBitWhenSpecialAnimDone(u8 taskId)
{
gAnimScriptCallback();
if (!gAnimScriptActive)
{
2018-02-08 12:13:29 +01:00
gBattleSpritesDataPtr->healthBoxesData[gTasks[taskId].tBattlerId].specialAnimActive = 0;
2017-11-04 16:11:13 +01:00
DestroyTask(taskId);
}
}
2018-02-08 12:13:29 +01:00
#undef tBattlerId
2017-11-04 16:11:13 +01:00
2018-07-01 11:15:42 +02:00
// Great function to include newly added moves that don't have animation yet.
2017-11-04 16:11:13 +01:00
bool8 IsMoveWithoutAnimation(u16 moveId, u8 animationTurn)
{
return FALSE;
}
2018-02-08 12:13:29 +01:00
bool8 mplay_80342A4(u8 battlerId)
2017-11-04 16:11:13 +01:00
{
u8 zero = 0;
if (IsSEPlaying())
{
2018-02-08 12:13:29 +01:00
gBattleSpritesDataPtr->healthBoxesData[battlerId].field_8++;
2018-02-06 02:46:59 +01:00
if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_8 < 30)
2017-11-04 16:11:13 +01:00
return TRUE;
m4aMPlayStop(&gMPlayInfo_SE1);
m4aMPlayStop(&gMPlayInfo_SE2);
2017-11-04 16:11:13 +01:00
}
if (zero == 0)
{
2018-02-08 12:13:29 +01:00
gBattleSpritesDataPtr->healthBoxesData[battlerId].field_8 = 0;
2017-11-04 16:11:13 +01:00
return FALSE;
}
return TRUE;
}
2018-02-08 12:13:29 +01:00
void BattleLoadOpponentMonSpriteGfx(struct Pokemon *mon, u8 battlerId)
2017-11-04 16:11:13 +01:00
{
u32 monsPersonality, currentPersonality, otId;
u16 species;
2018-01-16 23:42:31 +01:00
u8 position;
2017-11-04 16:11:13 +01:00
u16 paletteOffset;
const void *lzPaletteData;
monsPersonality = GetMonData(mon, MON_DATA_PERSONALITY);
2018-02-08 12:13:29 +01:00
if (gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies == SPECIES_NONE)
2017-11-04 16:11:13 +01:00
{
species = GetMonData(mon, MON_DATA_SPECIES);
currentPersonality = monsPersonality;
}
else
{
2018-02-08 12:13:29 +01:00
species = gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies;
currentPersonality = gTransformedPersonalities[battlerId];
2017-11-04 16:11:13 +01:00
}
otId = GetMonData(mon, MON_DATA_OT_ID);
2018-02-08 12:13:29 +01:00
position = GetBattlerPosition(battlerId);
2017-11-04 16:11:13 +01:00
HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species],
2018-01-16 23:42:31 +01:00
gMonSpritesGfxPtr->sprites[position],
2017-11-04 16:11:13 +01:00
species, currentPersonality);
2018-02-08 12:13:29 +01:00
paletteOffset = 0x100 + battlerId * 16;
2017-11-04 16:11:13 +01:00
2018-02-08 12:13:29 +01:00
if (gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies == SPECIES_NONE)
2017-11-04 16:11:13 +01:00
lzPaletteData = GetMonFrontSpritePal(mon);
else
2019-07-25 18:56:08 +02:00
lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(species, otId, monsPersonality);
2017-11-04 16:11:13 +01:00
LZDecompressWram(lzPaletteData, gDecompressionBuffer);
LoadPalette(gDecompressionBuffer, paletteOffset, 0x20);
2018-02-08 12:13:29 +01:00
LoadPalette(gDecompressionBuffer, 0x80 + battlerId * 16, 0x20);
2017-11-04 16:11:13 +01:00
if (species == SPECIES_CASTFORM)
{
2018-02-08 12:13:29 +01:00
paletteOffset = 0x100 + battlerId * 16;
2017-11-04 16:11:13 +01:00
LZDecompressWram(lzPaletteData, gBattleStruct->castformPalette[0]);
2018-02-08 12:13:29 +01:00
LoadPalette(gBattleStruct->castformPalette[gBattleMonForms[battlerId]], paletteOffset, 0x20);
2017-11-04 16:11:13 +01:00
}
// transform's pink color
2018-02-08 12:13:29 +01:00
if (gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies != SPECIES_NONE)
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
BlendPalette(paletteOffset, 16, 6, RGB_WHITE);
2017-11-04 16:11:13 +01:00
CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, 32);
}
}
2018-02-08 12:13:29 +01:00
void BattleLoadPlayerMonSpriteGfx(struct Pokemon *mon, u8 battlerId)
2017-11-04 16:11:13 +01:00
{
u32 monsPersonality, currentPersonality, otId;
u16 species;
2018-01-16 23:42:31 +01:00
u8 position;
2017-11-04 16:11:13 +01:00
u16 paletteOffset;
const void *lzPaletteData;
monsPersonality = GetMonData(mon, MON_DATA_PERSONALITY);
2018-02-08 12:13:29 +01:00
if (gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies == SPECIES_NONE)
2017-11-04 16:11:13 +01:00
{
species = GetMonData(mon, MON_DATA_SPECIES);
currentPersonality = monsPersonality;
}
else
{
2018-02-08 12:13:29 +01:00
species = gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies;
currentPersonality = gTransformedPersonalities[battlerId];
2017-11-04 16:11:13 +01:00
}
otId = GetMonData(mon, MON_DATA_OT_ID);
2018-02-08 12:13:29 +01:00
position = GetBattlerPosition(battlerId);
2017-11-04 16:11:13 +01:00
2018-02-08 12:13:29 +01:00
if (sub_80688F8(1, battlerId) == 1 || gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies != SPECIES_NONE)
2017-11-04 16:11:13 +01:00
{
HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonBackPicTable[species],
2018-01-16 23:42:31 +01:00
gMonSpritesGfxPtr->sprites[position],
2017-11-04 16:11:13 +01:00
species, currentPersonality);
}
else
{
HandleLoadSpecialPokePic(&gMonBackPicTable[species],
2018-01-16 23:42:31 +01:00
gMonSpritesGfxPtr->sprites[position],
2017-11-04 16:11:13 +01:00
species, currentPersonality);
}
2018-02-08 12:13:29 +01:00
paletteOffset = 0x100 + battlerId * 16;
2017-11-04 16:11:13 +01:00
2018-02-08 12:13:29 +01:00
if (gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies == SPECIES_NONE)
2017-11-04 16:11:13 +01:00
lzPaletteData = GetMonFrontSpritePal(mon);
else
2019-07-25 18:56:08 +02:00
lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(species, otId, monsPersonality);
2017-11-04 16:11:13 +01:00
LZDecompressWram(lzPaletteData, gDecompressionBuffer);
LoadPalette(gDecompressionBuffer, paletteOffset, 0x20);
2018-02-08 12:13:29 +01:00
LoadPalette(gDecompressionBuffer, 0x80 + battlerId * 16, 0x20);
2017-11-04 16:11:13 +01:00
if (species == SPECIES_CASTFORM)
{
2018-02-08 12:13:29 +01:00
paletteOffset = 0x100 + battlerId * 16;
2017-11-04 16:11:13 +01:00
LZDecompressWram(lzPaletteData, gBattleStruct->castformPalette[0]);
2018-02-08 12:13:29 +01:00
LoadPalette(gBattleStruct->castformPalette[gBattleMonForms[battlerId]], paletteOffset, 0x20);
2017-11-04 16:11:13 +01:00
}
// transform's pink color
2018-02-08 12:13:29 +01:00
if (gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies != SPECIES_NONE)
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
BlendPalette(paletteOffset, 16, 6, RGB_WHITE);
2017-11-04 16:11:13 +01:00
CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, 32);
}
}
void nullsub_23(void)
{
}
void nullsub_24(u16 species)
{
}
2018-02-08 12:13:29 +01:00
void DecompressTrainerFrontPic(u16 frontPicId, u8 battlerId)
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
u8 position = GetBattlerPosition(battlerId);
2017-11-04 16:11:13 +01:00
DecompressPicFromTable_2(&gTrainerFrontPicTable[frontPicId],
2018-01-16 23:42:31 +01:00
gMonSpritesGfxPtr->sprites[position],
2017-11-04 16:11:13 +01:00
SPECIES_NONE);
2018-12-17 23:00:08 +01:00
LoadCompressedSpritePalette(&gTrainerFrontPicPaletteTable[frontPicId]);
2017-11-04 16:11:13 +01:00
}
2018-02-08 12:13:29 +01:00
void DecompressTrainerBackPic(u16 backPicId, u8 battlerId)
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
u8 position = GetBattlerPosition(battlerId);
2017-11-04 16:11:13 +01:00
DecompressPicFromTable_2(&gTrainerBackPicTable[backPicId],
2018-01-16 23:42:31 +01:00
gMonSpritesGfxPtr->sprites[position],
2017-11-04 16:11:13 +01:00
SPECIES_NONE);
LoadCompressedPalette(gTrainerBackPicPaletteTable[backPicId].data,
2018-02-08 12:13:29 +01:00
0x100 + 16 * battlerId, 0x20);
2017-11-04 16:11:13 +01:00
}
void nullsub_25(u8 arg0)
{
}
void FreeTrainerFrontPicPalette(u16 frontPicId)
{
FreeSpritePaletteByTag(gTrainerFrontPicPaletteTable[frontPicId].tag);
}
2018-07-01 11:15:42 +02:00
// Unused.
void BattleLoadAllHealthBoxesGfxAtOnce(void)
2017-11-04 16:11:13 +01:00
{
2018-06-19 00:43:15 +02:00
u8 numberOfBattlers = 0;
2017-11-04 16:11:13 +01:00
u8 i;
2018-07-01 11:15:42 +02:00
LoadSpritePalette(&sSpritePalettes_HealthBoxHealthBar[0]);
LoadSpritePalette(&sSpritePalettes_HealthBoxHealthBar[1]);
2017-11-04 16:11:13 +01:00
if (!IsDoubleBattle())
{
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheet_SinglesPlayerHealthbox);
LoadCompressedSpriteSheet(&sSpriteSheet_SinglesOpponentHealthbox);
2018-06-19 00:43:15 +02:00
numberOfBattlers = 2;
2017-11-04 16:11:13 +01:00
}
else
{
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheets_DoublesPlayerHealthbox[0]);
LoadCompressedSpriteSheet(&sSpriteSheets_DoublesPlayerHealthbox[1]);
LoadCompressedSpriteSheet(&sSpriteSheets_DoublesOpponentHealthbox[0]);
LoadCompressedSpriteSheet(&sSpriteSheets_DoublesOpponentHealthbox[1]);
numberOfBattlers = MAX_BATTLERS_COUNT;
2017-11-04 16:11:13 +01:00
}
2018-06-19 00:43:15 +02:00
for (i = 0; i < numberOfBattlers; i++)
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheets_HealthBar[gBattlerPositions[i]]);
2017-11-04 16:11:13 +01:00
}
bool8 BattleLoadAllHealthBoxesGfx(u8 state)
{
bool8 retVal = FALSE;
if (state != 0)
{
if (state == 1)
{
2018-07-01 11:15:42 +02:00
LoadSpritePalette(&sSpritePalettes_HealthBoxHealthBar[0]);
LoadSpritePalette(&sSpritePalettes_HealthBoxHealthBar[1]);
2017-11-04 16:11:13 +01:00
}
else if (!IsDoubleBattle())
{
if (state == 2)
{
if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheet_SafariHealthbox);
2017-11-04 16:11:13 +01:00
else
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheet_SinglesPlayerHealthbox);
2017-11-04 16:11:13 +01:00
}
else if (state == 3)
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheet_SinglesOpponentHealthbox);
2017-11-04 16:11:13 +01:00
else if (state == 4)
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheets_HealthBar[gBattlerPositions[0]]);
2017-11-04 16:11:13 +01:00
else if (state == 5)
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheets_HealthBar[gBattlerPositions[1]]);
2017-11-04 16:11:13 +01:00
else
retVal = TRUE;
}
else
{
if (state == 2)
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheets_DoublesPlayerHealthbox[0]);
2017-11-04 16:11:13 +01:00
else if (state == 3)
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheets_DoublesPlayerHealthbox[1]);
2017-11-04 16:11:13 +01:00
else if (state == 4)
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheets_DoublesOpponentHealthbox[0]);
2017-11-04 16:11:13 +01:00
else if (state == 5)
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheets_DoublesOpponentHealthbox[1]);
2017-11-04 16:11:13 +01:00
else if (state == 6)
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheets_HealthBar[gBattlerPositions[0]]);
2017-11-04 16:11:13 +01:00
else if (state == 7)
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheets_HealthBar[gBattlerPositions[1]]);
2017-11-04 16:11:13 +01:00
else if (state == 8)
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheets_HealthBar[gBattlerPositions[2]]);
2017-11-04 16:11:13 +01:00
else if (state == 9)
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&sSpriteSheets_HealthBar[gBattlerPositions[3]]);
2017-11-04 16:11:13 +01:00
else
retVal = TRUE;
}
}
return retVal;
}
void LoadBattleBarGfx(u8 arg0)
{
LZDecompressWram(gUnknown_08C093F0, gMonSpritesGfxPtr->barFontGfx);
}
2018-02-08 12:13:29 +01:00
bool8 BattleInitAllSprites(u8 *state1, u8 *battlerId)
2017-11-04 16:11:13 +01:00
{
bool8 retVal = FALSE;
switch (*state1)
{
case 0:
2018-06-19 00:43:15 +02:00
ClearSpritesBattlerHealthboxAnimData();
2017-11-04 16:11:13 +01:00
(*state1)++;
break;
case 1:
2018-02-08 12:13:29 +01:00
if (!BattleLoadAllHealthBoxesGfx(*battlerId))
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
(*battlerId)++;
2017-11-04 16:11:13 +01:00
}
else
{
2018-02-08 12:13:29 +01:00
*battlerId = 0;
2017-11-04 16:11:13 +01:00
(*state1)++;
}
break;
case 2:
(*state1)++;
break;
case 3:
2018-02-08 12:13:29 +01:00
if ((gBattleTypeFlags & BATTLE_TYPE_SAFARI) && *battlerId == 0)
gHealthboxSpriteIds[*battlerId] = CreateSafariPlayerHealthboxSprites();
2017-11-04 16:11:13 +01:00
else
2018-02-08 12:13:29 +01:00
gHealthboxSpriteIds[*battlerId] = CreateBattlerHealthboxSprites(*battlerId);
2017-11-04 16:11:13 +01:00
2018-02-08 12:13:29 +01:00
(*battlerId)++;
if (*battlerId == gBattlersCount)
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
*battlerId = 0;
2017-11-04 16:11:13 +01:00
(*state1)++;
}
break;
case 4:
2018-02-08 12:13:29 +01:00
InitBattlerHealthboxCoords(*battlerId);
2019-09-04 23:45:04 +02:00
if (gBattlerPositions[*battlerId] <= B_POSITION_OPPONENT_LEFT)
2018-02-08 12:13:29 +01:00
DummyBattleInterfaceFunc(gHealthboxSpriteIds[*battlerId], FALSE);
2017-11-04 16:11:13 +01:00
else
2018-02-08 12:13:29 +01:00
DummyBattleInterfaceFunc(gHealthboxSpriteIds[*battlerId], TRUE);
2017-11-04 16:11:13 +01:00
2018-02-08 12:13:29 +01:00
(*battlerId)++;
if (*battlerId == gBattlersCount)
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
*battlerId = 0;
2017-11-04 16:11:13 +01:00
(*state1)++;
}
break;
case 5:
2018-02-08 12:13:29 +01:00
if (GetBattlerSide(*battlerId) == B_SIDE_PLAYER)
2017-11-04 16:11:13 +01:00
{
if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI))
2018-02-08 12:13:29 +01:00
UpdateHealthboxAttribute(gHealthboxSpriteIds[*battlerId], &gPlayerParty[gBattlerPartyIndexes[*battlerId]], HEALTHBOX_ALL);
2017-11-04 16:11:13 +01:00
}
else
{
2018-02-08 12:13:29 +01:00
UpdateHealthboxAttribute(gHealthboxSpriteIds[*battlerId], &gEnemyParty[gBattlerPartyIndexes[*battlerId]], HEALTHBOX_ALL);
2017-11-04 16:11:13 +01:00
}
2018-02-08 12:13:29 +01:00
SetHealthboxSpriteInvisible(gHealthboxSpriteIds[*battlerId]);
(*battlerId)++;
if (*battlerId == gBattlersCount)
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
*battlerId = 0;
2017-11-04 16:11:13 +01:00
(*state1)++;
}
break;
case 6:
LoadAndCreateEnemyShadowSprites();
2019-10-31 19:11:55 +01:00
BufferBattlePartyCurrentOrder();
2017-11-04 16:11:13 +01:00
retVal = TRUE;
break;
}
return retVal;
}
void ClearSpritesHealthboxAnimData(void)
{
2018-02-06 02:46:59 +01:00
memset(gBattleSpritesDataPtr->healthBoxesData, 0, sizeof(struct BattleHealthboxInfo) * MAX_BATTLERS_COUNT);
2017-11-04 16:11:13 +01:00
memset(gBattleSpritesDataPtr->animationData, 0, sizeof(struct BattleAnimationInfo));
}
2018-06-19 00:43:15 +02:00
static void ClearSpritesBattlerHealthboxAnimData(void)
2017-11-04 16:11:13 +01:00
{
ClearSpritesHealthboxAnimData();
2018-02-06 23:09:39 +01:00
memset(gBattleSpritesDataPtr->battlerData, 0, sizeof(struct BattleSpriteInfo) * MAX_BATTLERS_COUNT);
2017-11-04 16:11:13 +01:00
}
void CopyAllBattleSpritesInvisibilities(void)
{
s32 i;
2018-02-06 02:46:59 +01:00
for (i = 0; i < gBattlersCount; i++)
2018-02-06 23:09:39 +01:00
gBattleSpritesDataPtr->battlerData[i].invisible = gSprites[gBattlerSpriteIds[i]].invisible;
2017-11-04 16:11:13 +01:00
}
2018-02-08 12:13:29 +01:00
void CopyBattleSpriteInvisibility(u8 battlerId)
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
gBattleSpritesDataPtr->battlerData[battlerId].invisible = gSprites[gBattlerSpriteIds[battlerId]].invisible;
2017-11-04 16:11:13 +01:00
}
2018-06-19 00:43:15 +02:00
void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool8 notTransform)
2017-11-04 16:11:13 +01:00
{
u16 paletteOffset;
u32 personalityValue;
u32 otId;
2018-01-16 23:42:31 +01:00
u8 position;
2018-10-21 09:24:57 +02:00
const u32 *lzPaletteData;
2017-11-04 16:11:13 +01:00
if (notTransform)
{
2018-06-19 00:43:15 +02:00
StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerAtk]], gBattleSpritesDataPtr->animationData->animArg);
paletteOffset = 0x100 + battlerAtk * 16;
2017-11-04 16:11:13 +01:00
LoadPalette(gBattleStruct->castformPalette[gBattleSpritesDataPtr->animationData->animArg], paletteOffset, 32);
2018-06-19 00:43:15 +02:00
gBattleMonForms[battlerAtk] = gBattleSpritesDataPtr->animationData->animArg;
if (gBattleSpritesDataPtr->battlerData[battlerAtk].transformSpecies != SPECIES_NONE)
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
BlendPalette(paletteOffset, 16, 6, RGB_WHITE);
2017-11-04 16:11:13 +01:00
CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, 32);
}
2018-06-19 00:43:15 +02:00
gSprites[gBattlerSpriteIds[battlerAtk]].pos1.y = GetBattlerSpriteDefault_Y(battlerAtk);
2017-11-04 16:11:13 +01:00
}
else
{
const void *src;
void *dst;
u16 targetSpecies;
if (IsContest())
{
2018-01-16 23:42:31 +01:00
position = 0;
2020-08-14 01:10:23 +02:00
targetSpecies = gContestResources->moveAnim->targetSpecies;
personalityValue = gContestResources->moveAnim->personality;
otId = gContestResources->moveAnim->otId;
2017-11-04 16:11:13 +01:00
HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonBackPicTable[targetSpecies],
gMonSpritesGfxPtr->sprites[0],
targetSpecies,
2020-08-14 01:10:23 +02:00
gContestResources->moveAnim->targetPersonality);
2017-11-04 16:11:13 +01:00
}
else
{
2018-06-19 00:43:15 +02:00
position = GetBattlerPosition(battlerAtk);
2017-11-04 16:11:13 +01:00
2018-06-19 00:43:15 +02:00
if (GetBattlerSide(battlerDef) == B_SIDE_OPPONENT)
targetSpecies = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerDef]], MON_DATA_SPECIES);
2017-11-04 16:11:13 +01:00
else
2018-06-19 00:43:15 +02:00
targetSpecies = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerDef]], MON_DATA_SPECIES);
2017-11-04 16:11:13 +01:00
2018-06-19 00:43:15 +02:00
if (GetBattlerSide(battlerAtk) == B_SIDE_PLAYER)
2017-11-04 16:11:13 +01:00
{
2018-06-19 00:43:15 +02:00
personalityValue = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY);
otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID);
2017-11-04 16:11:13 +01:00
HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonBackPicTable[targetSpecies],
2018-01-16 23:42:31 +01:00
gMonSpritesGfxPtr->sprites[position],
2017-11-04 16:11:13 +01:00
targetSpecies,
2018-06-19 00:43:15 +02:00
gTransformedPersonalities[battlerAtk]);
2017-11-04 16:11:13 +01:00
}
else
{
2018-06-19 00:43:15 +02:00
personalityValue = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY);
otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID);
2017-11-04 16:11:13 +01:00
HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[targetSpecies],
2018-01-16 23:42:31 +01:00
gMonSpritesGfxPtr->sprites[position],
2017-11-04 16:11:13 +01:00
targetSpecies,
2018-06-19 00:43:15 +02:00
gTransformedPersonalities[battlerAtk]);
2017-11-04 16:11:13 +01:00
}
}
2018-01-16 23:42:31 +01:00
src = gMonSpritesGfxPtr->sprites[position];
2020-09-02 20:14:29 +02:00
dst = (void *)(OBJ_VRAM0 + gSprites[gBattlerSpriteIds[battlerAtk]].oam.tileNum * 32);
2017-11-04 16:11:13 +01:00
DmaCopy32(3, src, dst, 0x800);
2018-06-19 00:43:15 +02:00
paletteOffset = 0x100 + battlerAtk * 16;
2019-07-25 18:56:08 +02:00
lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(targetSpecies, otId, personalityValue);
2017-11-04 16:11:13 +01:00
LZDecompressWram(lzPaletteData, gDecompressionBuffer);
LoadPalette(gDecompressionBuffer, paletteOffset, 32);
if (targetSpecies == SPECIES_CASTFORM)
{
2019-04-04 23:53:06 +02:00
gSprites[gBattlerSpriteIds[battlerAtk]].anims = gMonFrontAnimsPtrTable[targetSpecies];
2017-11-04 16:11:13 +01:00
LZDecompressWram(lzPaletteData, gBattleStruct->castformPalette[0]);
2018-06-19 00:43:15 +02:00
LoadPalette(gBattleStruct->castformPalette[0] + gBattleMonForms[battlerDef] * 16, paletteOffset, 32);
2017-11-04 16:11:13 +01:00
}
2018-02-08 12:13:29 +01:00
BlendPalette(paletteOffset, 16, 6, RGB_WHITE);
2017-11-04 16:11:13 +01:00
CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, 32);
if (!IsContest())
{
2018-06-19 00:43:15 +02:00
gBattleSpritesDataPtr->battlerData[battlerAtk].transformSpecies = targetSpecies;
gBattleMonForms[battlerAtk] = gBattleMonForms[battlerDef];
2017-11-04 16:11:13 +01:00
}
2018-06-19 00:43:15 +02:00
gSprites[gBattlerSpriteIds[battlerAtk]].pos1.y = GetBattlerSpriteDefault_Y(battlerAtk);
StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerAtk]], gBattleMonForms[battlerAtk]);
2017-11-04 16:11:13 +01:00
}
}
2018-02-08 12:13:29 +01:00
void BattleLoadSubstituteOrMonSpriteGfx(u8 battlerId, bool8 loadMonSprite)
2017-11-04 16:11:13 +01:00
{
2019-07-29 21:09:05 +02:00
s32 i, position, palOffset;
2017-11-04 16:11:13 +01:00
if (!loadMonSprite)
{
if (IsContest())
2018-01-16 23:42:31 +01:00
position = 0;
2017-11-04 16:11:13 +01:00
else
2018-02-08 12:13:29 +01:00
position = GetBattlerPosition(battlerId);
2017-11-04 16:11:13 +01:00
if (IsContest())
2018-01-16 23:42:31 +01:00
LZDecompressVram(gSubstituteDollTilemap, gMonSpritesGfxPtr->sprites[position]);
2018-02-08 12:13:29 +01:00
else if (GetBattlerSide(battlerId) != B_SIDE_PLAYER)
2018-01-16 23:42:31 +01:00
LZDecompressVram(gSubstituteDollGfx, gMonSpritesGfxPtr->sprites[position]);
2017-11-04 16:11:13 +01:00
else
2018-01-16 23:42:31 +01:00
LZDecompressVram(gSubstituteDollTilemap, gMonSpritesGfxPtr->sprites[position]);
2017-11-04 16:11:13 +01:00
2019-07-29 21:09:05 +02:00
for (i = 1; i < 4; i++)
2017-11-04 16:11:13 +01:00
{
2019-07-29 21:09:05 +02:00
u8 (*ptr)[4][0x800] = gMonSpritesGfxPtr->sprites[position];
ptr++;ptr--; // Needed to match.
DmaCopy32Defvars(3, (*ptr)[0], (*ptr)[i], 0x800);
2017-11-04 16:11:13 +01:00
}
2019-07-29 21:09:05 +02:00
palOffset = (battlerId * 16) + 0x100;
LoadCompressedPalette(gSubstituteDollPal, palOffset, 32);
2017-11-04 16:11:13 +01:00
}
2020-08-28 20:35:37 +02:00
else if (!IsContest())
2017-11-04 16:11:13 +01:00
{
2020-08-28 20:35:37 +02:00
if (GetBattlerSide(battlerId) != B_SIDE_PLAYER)
BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[battlerId]], battlerId);
else
BattleLoadPlayerMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[battlerId]], battlerId);
2017-11-04 16:11:13 +01:00
}
}
2018-02-08 12:13:29 +01:00
void LoadBattleMonGfxAndAnimate(u8 battlerId, bool8 loadMonSprite, u8 spriteId)
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
BattleLoadSubstituteOrMonSpriteGfx(battlerId, loadMonSprite);
StartSpriteAnim(&gSprites[spriteId], gBattleMonForms[battlerId]);
2017-11-04 16:11:13 +01:00
if (!loadMonSprite)
2018-02-08 12:13:29 +01:00
gSprites[spriteId].pos1.y = GetSubstituteSpriteDefault_Y(battlerId);
2017-11-04 16:11:13 +01:00
else
2018-02-08 12:13:29 +01:00
gSprites[spriteId].pos1.y = GetBattlerSpriteDefault_Y(battlerId);
2017-11-04 16:11:13 +01:00
}
2018-02-08 12:13:29 +01:00
void TrySetBehindSubstituteSpriteBit(u8 battlerId, u16 move)
2017-11-04 16:11:13 +01:00
{
if (move == MOVE_SUBSTITUTE)
2018-02-08 12:13:29 +01:00
gBattleSpritesDataPtr->battlerData[battlerId].behindSubstitute = 1;
2017-11-04 16:11:13 +01:00
}
2018-02-08 12:13:29 +01:00
void ClearBehindSubstituteBit(u8 battlerId)
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
gBattleSpritesDataPtr->battlerData[battlerId].behindSubstitute = 0;
2017-11-04 16:11:13 +01:00
}
2018-02-08 12:13:29 +01:00
void HandleLowHpMusicChange(struct Pokemon *mon, u8 battlerId)
2017-11-04 16:11:13 +01:00
{
u16 hp = GetMonData(mon, MON_DATA_HP);
u16 maxHP = GetMonData(mon, MON_DATA_MAX_HP);
if (GetHPBarLevel(hp, maxHP) == HP_BAR_RED)
{
2018-02-08 12:13:29 +01:00
if (!gBattleSpritesDataPtr->battlerData[battlerId].lowHpSong)
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
if (!gBattleSpritesDataPtr->battlerData[battlerId ^ BIT_FLANK].lowHpSong)
2020-08-21 00:02:00 +02:00
PlaySE(SE_LOW_HEALTH);
2018-02-08 12:13:29 +01:00
gBattleSpritesDataPtr->battlerData[battlerId].lowHpSong = 1;
2017-11-04 16:11:13 +01:00
}
}
else
{
2018-02-08 12:13:29 +01:00
gBattleSpritesDataPtr->battlerData[battlerId].lowHpSong = 0;
2017-11-04 16:11:13 +01:00
if (!IsDoubleBattle())
{
2020-08-21 00:02:00 +02:00
m4aSongNumStop(SE_LOW_HEALTH);
2017-11-04 16:11:13 +01:00
return;
}
2018-02-08 12:13:29 +01:00
if (IsDoubleBattle() && !gBattleSpritesDataPtr->battlerData[battlerId ^ BIT_FLANK].lowHpSong)
2017-11-04 16:11:13 +01:00
{
2020-08-21 00:02:00 +02:00
m4aSongNumStop(SE_LOW_HEALTH);
2017-11-04 16:11:13 +01:00
return;
}
}
}
void BattleStopLowHpSound(void)
{
2018-06-19 00:43:15 +02:00
u8 playerBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
2017-11-04 16:11:13 +01:00
2018-06-19 00:43:15 +02:00
gBattleSpritesDataPtr->battlerData[playerBattler].lowHpSong = 0;
2017-11-04 16:11:13 +01:00
if (IsDoubleBattle())
2018-06-19 00:43:15 +02:00
gBattleSpritesDataPtr->battlerData[playerBattler ^ BIT_FLANK].lowHpSong = 0;
2017-11-04 16:11:13 +01:00
2020-08-21 00:02:00 +02:00
m4aSongNumStop(SE_LOW_HEALTH);
2017-11-04 16:11:13 +01:00
}
u8 GetMonHPBarLevel(struct Pokemon *mon)
{
u16 hp = GetMonData(mon, MON_DATA_HP);
u16 maxHP = GetMonData(mon, MON_DATA_MAX_HP);
return GetHPBarLevel(hp, maxHP);
}
2018-06-19 00:43:15 +02:00
void HandleBattleLowHpMusicChange(void)
2017-11-04 16:11:13 +01:00
{
if (gMain.inBattle)
{
2018-06-19 00:43:15 +02:00
u8 playerBattler1 = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
u8 playerBattler2 = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
2019-10-26 03:55:01 +02:00
u8 battler1PartyId = GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[playerBattler1]);
u8 battler2PartyId = GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[playerBattler2]);
2018-06-19 00:43:15 +02:00
if (GetMonData(&gPlayerParty[battler1PartyId], MON_DATA_HP) != 0)
HandleLowHpMusicChange(&gPlayerParty[battler1PartyId], playerBattler1);
if (IsDoubleBattle() && GetMonData(&gPlayerParty[battler2PartyId], MON_DATA_HP) != 0)
HandleLowHpMusicChange(&gPlayerParty[battler2PartyId], playerBattler2);
2017-11-04 16:11:13 +01:00
}
}
void sub_805EB9C(u8 affineMode)
{
s32 i;
2018-02-06 02:46:59 +01:00
for (i = 0; i < gBattlersCount; i++)
2017-11-04 16:11:13 +01:00
{
2018-02-06 20:48:02 +01:00
if (IsBattlerSpritePresent(i))
2017-11-04 16:11:13 +01:00
{
2018-02-06 20:48:02 +01:00
gSprites[gBattlerSpriteIds[i]].oam.affineMode = affineMode;
2018-12-18 05:08:08 +01:00
if (affineMode == ST_OAM_AFFINE_OFF)
2017-11-04 16:11:13 +01:00
{
2018-12-18 05:08:08 +01:00
gBattleSpritesDataPtr->healthBoxesData[i].matrixNum = gSprites[gBattlerSpriteIds[i]].oam.matrixNum;
2018-02-06 20:48:02 +01:00
gSprites[gBattlerSpriteIds[i]].oam.matrixNum = 0;
2017-11-04 16:11:13 +01:00
}
else
{
2018-12-18 05:08:08 +01:00
gSprites[gBattlerSpriteIds[i]].oam.matrixNum = gBattleSpritesDataPtr->healthBoxesData[i].matrixNum;
2017-11-04 16:11:13 +01:00
}
}
}
}
2018-02-08 12:13:29 +01:00
#define tBattlerId data[0]
2017-11-04 16:11:13 +01:00
void LoadAndCreateEnemyShadowSprites(void)
{
2018-02-08 12:13:29 +01:00
u8 battlerId;
2017-11-04 16:11:13 +01:00
2018-12-17 23:00:08 +01:00
LoadCompressedSpriteSheet(&gSpriteSheet_EnemyShadow);
2017-11-04 16:11:13 +01:00
2018-02-08 12:13:29 +01:00
battlerId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
gBattleSpritesDataPtr->healthBoxesData[battlerId].shadowSpriteId = CreateSprite(&gSpriteTemplate_EnemyShadow, GetBattlerSpriteCoord(battlerId, 0), GetBattlerSpriteCoord(battlerId, 1) + 29, 0xC8);
gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerId].shadowSpriteId].data[0] = battlerId;
2017-11-04 16:11:13 +01:00
if (IsDoubleBattle())
{
2018-02-08 12:13:29 +01:00
battlerId = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
gBattleSpritesDataPtr->healthBoxesData[battlerId].shadowSpriteId = CreateSprite(&gSpriteTemplate_EnemyShadow, GetBattlerSpriteCoord(battlerId, 0), GetBattlerSpriteCoord(battlerId, 1) + 29, 0xC8);
gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerId].shadowSpriteId].data[0] = battlerId;
2017-11-04 16:11:13 +01:00
}
}
void SpriteCB_EnemyShadow(struct Sprite *shadowSprite)
{
bool8 invisible = FALSE;
2018-02-08 12:13:29 +01:00
u8 battlerId = shadowSprite->tBattlerId;
2018-06-19 00:43:15 +02:00
struct Sprite *battlerSprite = &gSprites[gBattlerSpriteIds[battlerId]];
2017-11-04 16:11:13 +01:00
2018-06-19 00:43:15 +02:00
if (!battlerSprite->inUse || !IsBattlerSpritePresent(battlerId))
2017-11-04 16:11:13 +01:00
{
shadowSprite->callback = SpriteCB_SetInvisible;
return;
}
2018-06-19 00:43:15 +02:00
if (gAnimScriptActive || battlerSprite->invisible)
2017-11-04 16:11:13 +01:00
invisible = TRUE;
2018-02-08 12:13:29 +01:00
else if (gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies != SPECIES_NONE
&& gEnemyMonElevation[gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies] == 0)
2017-11-04 16:11:13 +01:00
invisible = TRUE;
2018-02-08 12:13:29 +01:00
if (gBattleSpritesDataPtr->battlerData[battlerId].behindSubstitute)
2017-11-04 16:11:13 +01:00
invisible = TRUE;
2018-06-19 00:43:15 +02:00
shadowSprite->pos1.x = battlerSprite->pos1.x;
shadowSprite->pos2.x = battlerSprite->pos2.x;
2017-11-04 16:11:13 +01:00
shadowSprite->invisible = invisible;
}
2018-02-08 12:13:29 +01:00
#undef tBattlerId
2017-11-04 16:11:13 +01:00
void SpriteCB_SetInvisible(struct Sprite *sprite)
{
sprite->invisible = TRUE;
2017-11-04 16:11:13 +01:00
}
2018-02-08 12:13:29 +01:00
void SetBattlerShadowSpriteCallback(u8 battlerId, u16 species)
2017-11-04 16:11:13 +01:00
{
2018-06-19 00:43:15 +02:00
// The player's shadow is never seen.
2018-02-08 12:13:29 +01:00
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
2017-11-04 16:11:13 +01:00
return;
2018-02-08 12:13:29 +01:00
if (gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies != SPECIES_NONE)
species = gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies;
2017-11-04 16:11:13 +01:00
if (gEnemyMonElevation[species] != 0)
2018-02-08 12:13:29 +01:00
gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerId].shadowSpriteId].callback = SpriteCB_EnemyShadow;
2017-11-04 16:11:13 +01:00
else
2018-02-08 12:13:29 +01:00
gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerId].shadowSpriteId].callback = SpriteCB_SetInvisible;
2017-11-04 16:11:13 +01:00
}
2018-02-08 12:13:29 +01:00
void HideBattlerShadowSprite(u8 battlerId)
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerId].shadowSpriteId].callback = SpriteCB_SetInvisible;
2017-11-04 16:11:13 +01:00
}
void sub_805EF14(void)
{
u16 *vramPtr = (u16*)(VRAM + 0x240);
s32 i;
s32 j;
for (i = 0; i < 9; i++)
{
for (j = 0; j < 16; j++)
{
if (!(*vramPtr & 0xF000))
*vramPtr |= 0xF000;
if (!(*vramPtr & 0x0F00))
*vramPtr |= 0x0F00;
if (!(*vramPtr & 0x00F0))
*vramPtr |= 0x00F0;
if (!(*vramPtr & 0x000F))
*vramPtr |= 0x000F;
vramPtr++;
}
}
}
2018-02-08 12:13:29 +01:00
void ClearTemporarySpeciesSpriteData(u8 battlerId, bool8 dontClearSubstitute)
2017-11-04 16:11:13 +01:00
{
2018-02-08 12:13:29 +01:00
gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies = SPECIES_NONE;
gBattleMonForms[battlerId] = 0;
2017-11-04 16:11:13 +01:00
if (!dontClearSubstitute)
2018-02-08 12:13:29 +01:00
ClearBehindSubstituteBit(battlerId);
2017-11-04 16:11:13 +01:00
}
void AllocateMonSpritesGfx(void)
{
u8 i = 0, j;
gMonSpritesGfxPtr = NULL;
gMonSpritesGfxPtr = AllocZeroed(sizeof(*gMonSpritesGfxPtr));
gMonSpritesGfxPtr->firstDecompressed = AllocZeroed(0x8000);
2018-02-06 02:46:59 +01:00
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
2017-11-04 16:11:13 +01:00
{
gMonSpritesGfxPtr->sprites[i] = gMonSpritesGfxPtr->firstDecompressed + (i * 0x2000);
*(gMonSpritesGfxPtr->templates + i) = gUnknown_08329D98[i];
for (j = 0; j < 4; j++)
{
gMonSpritesGfxPtr->field_74[i][j].data = gMonSpritesGfxPtr->sprites[i] + (j * 0x800);
gMonSpritesGfxPtr->field_74[i][j].size = 0x800;
}
gMonSpritesGfxPtr->templates[i].images = gMonSpritesGfxPtr->field_74[i];
}
gMonSpritesGfxPtr->barFontGfx = AllocZeroed(0x1000);
}
void FreeMonSpritesGfx(void)
{
if (gMonSpritesGfxPtr == NULL)
return;
2020-02-20 06:04:42 +01:00
if (gMonSpritesGfxPtr->buffer != NULL)
FREE_AND_SET_NULL(gMonSpritesGfxPtr->buffer);
2017-11-04 16:11:13 +01:00
if (gMonSpritesGfxPtr->field_178 != NULL)
FREE_AND_SET_NULL(gMonSpritesGfxPtr->field_178);
FREE_AND_SET_NULL(gMonSpritesGfxPtr->barFontGfx);
FREE_AND_SET_NULL(gMonSpritesGfxPtr->firstDecompressed);
gMonSpritesGfxPtr->sprites[0] = NULL;
gMonSpritesGfxPtr->sprites[1] = NULL;
gMonSpritesGfxPtr->sprites[2] = NULL;
gMonSpritesGfxPtr->sprites[3] = NULL;
FREE_AND_SET_NULL(gMonSpritesGfxPtr);
}
2018-06-19 00:43:15 +02:00
bool32 ShouldPlayNormalMonCry(struct Pokemon *mon)
2017-11-04 16:11:13 +01:00
{
s16 hp, maxHP;
s32 barLevel;
2018-01-16 22:12:38 +01:00
if (GetMonData(mon, MON_DATA_STATUS) & (STATUS1_ANY | STATUS1_TOXIC_COUNTER))
2017-11-04 16:11:13 +01:00
return FALSE;
hp = GetMonData(mon, MON_DATA_HP);
maxHP = GetMonData(mon, MON_DATA_MAX_HP);
barLevel = GetHPBarLevel(hp, maxHP);
if (barLevel <= HP_BAR_YELLOW)
return FALSE;
return TRUE;
}