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"
|
2020-09-19 19:37:24 +02:00
|
|
|
#include "dma3.h"
|
2019-09-09 03:07:54 +02:00
|
|
|
#include "malloc.h"
|
2018-10-21 09:24:57 +02:00
|
|
|
#include "graphics.h"
|
2017-12-05 19:27:33 +01:00
|
|
|
#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"
|
|
|
|
#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
|
|
|
|
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);
|
2021-01-23 02:03:21 +01:00
|
|
|
static void SpriteCB_TrainerSlideVertical(struct Sprite *sprite);
|
2021-05-07 02:49:04 +02:00
|
|
|
static bool8 ShouldAnimBeDoneRegardlessOfSubstitute(u8 animId);
|
2017-11-04 16:11:13 +01:00
|
|
|
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;
|
2018-12-05 15:31:01 +01:00
|
|
|
s32 chosenMoveId = -1;
|
2018-02-06 02:46:59 +01:00
|
|
|
struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleBufferA[gActiveBattler][4]);
|
2021-10-04 16:21:03 +02:00
|
|
|
u8 unusableMovesBits = CheckMoveLimitations(gActiveBattler, 0, MOVE_LIMITATIONS_ALL);
|
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
|
2021-08-25 00:59:32 +02:00
|
|
|
// Otherwise use move from "Support" group
|
2020-07-17 02:12:12 +02:00
|
|
|
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
|
|
|
|
2018-12-25 18:50:15 +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++;
|
|
|
|
|
2021-08-25 00:59:32 +02:00
|
|
|
|
2020-07-17 02:12:12 +02:00
|
|
|
// 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
|
|
|
|
{
|
2018-12-25 18:50:15 +01:00
|
|
|
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
|
|
|
|
{
|
2018-12-25 18:50:15 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2021-01-23 02:03:21 +01:00
|
|
|
// Wait for the pokemon to finish appearing out from the pokeball on send out
|
|
|
|
void SpriteCB_WaitForBattlerBallReleaseAnim(struct Sprite *sprite)
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-23 05:22:37 +01:00
|
|
|
static void UnusedDoBattleSpriteAffineAnim(struct Sprite *sprite, bool8 arg1)
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
2021-01-23 05:22:37 +01:00
|
|
|
sprite->animPaused = TRUE;
|
2017-11-04 16:11:13 +01:00
|
|
|
sprite->callback = SpriteCallbackDummy;
|
|
|
|
|
|
|
|
if (!arg1)
|
|
|
|
StartSpriteAffineAnim(sprite, 1);
|
|
|
|
else
|
|
|
|
StartSpriteAffineAnim(sprite, 1);
|
|
|
|
|
|
|
|
AnimateSprite(sprite);
|
|
|
|
}
|
|
|
|
|
2021-01-23 02:03:21 +01:00
|
|
|
#define sSpeedX data[0]
|
|
|
|
|
|
|
|
void SpriteCB_TrainerSlideIn(struct Sprite *sprite)
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
2018-02-08 11:17:41 +01:00
|
|
|
if (!(gIntroSlideFlags & 1))
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
2021-07-07 15:11:52 +02:00
|
|
|
sprite->x2 += sprite->sSpeedX;
|
|
|
|
if (sprite->x2 == 0)
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
2021-07-07 15:11:52 +02:00
|
|
|
if (sprite->y2 != 0)
|
2021-01-23 02:03:21 +01:00
|
|
|
sprite->callback = SpriteCB_TrainerSlideVertical;
|
2017-11-04 16:11:13 +01:00
|
|
|
else
|
|
|
|
sprite->callback = SpriteCallbackDummy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-23 02:03:21 +01:00
|
|
|
// Slide up to 0 if necessary (used by multi battle intro)
|
|
|
|
static void SpriteCB_TrainerSlideVertical(struct Sprite *sprite)
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
2021-07-07 15:11:52 +02:00
|
|
|
sprite->y2 -= 2;
|
|
|
|
if (sprite->y2 == 0)
|
2017-11-04 16:11:13 +01:00
|
|
|
sprite->callback = SpriteCallbackDummy;
|
|
|
|
}
|
|
|
|
|
2021-01-23 02:03:21 +01:00
|
|
|
#undef sSpeedX
|
|
|
|
|
2017-11-04 16:11:13 +01:00
|
|
|
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;
|
|
|
|
|
2021-10-04 16:21:03 +02:00
|
|
|
if (tableId == B_ANIM_CASTFORM_CHANGE && (argument & CASTFORM_SUBSTITUTE))
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
2021-10-04 16:21:03 +02:00
|
|
|
// If Castform is behind substitute, set the new form but skip the animation
|
|
|
|
gBattleMonForms[activeBattler] = (argument & ~CASTFORM_SUBSTITUTE);
|
2017-11-04 16:11:13 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
2018-06-19 00:43:15 +02:00
|
|
|
if (gBattleSpritesDataPtr->battlerData[activeBattler].behindSubstitute
|
2021-05-07 02:49:04 +02:00
|
|
|
&& !ShouldAnimBeDoneRegardlessOfSubstitute(tableId))
|
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
|
|
|
&& 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
|
|
|
|
2021-05-07 02:49:04 +02:00
|
|
|
static bool8 ShouldAnimBeDoneRegardlessOfSubstitute(u8 animId)
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-01-23 02:03:21 +01:00
|
|
|
// Check if SE has finished or 30 calls, whichever comes first
|
|
|
|
bool8 IsBattleSEPlaying(u8 battlerId)
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
|
|
|
u8 zero = 0;
|
|
|
|
|
|
|
|
if (IsSEPlaying())
|
|
|
|
{
|
2021-01-23 02:03:21 +01:00
|
|
|
gBattleSpritesDataPtr->healthBoxesData[battlerId].soundTimer++;
|
|
|
|
if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].soundTimer < 30)
|
2017-11-04 16:11:13 +01:00
|
|
|
return TRUE;
|
|
|
|
|
2018-01-10 04:30:54 +01:00
|
|
|
m4aMPlayStop(&gMPlayInfo_SE1);
|
|
|
|
m4aMPlayStop(&gMPlayInfo_SE2);
|
2017-11-04 16:11:13 +01:00
|
|
|
}
|
|
|
|
if (zero == 0)
|
|
|
|
{
|
2021-01-23 02:03:21 +01:00
|
|
|
gBattleSpritesDataPtr->healthBoxesData[battlerId].soundTimer = 0;
|
2017-11-04 16:11:13 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-01-23 02:03:21 +01:00
|
|
|
// Never reached
|
2017-11-04 16:11:13 +01:00
|
|
|
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],
|
2020-09-19 19:37:24 +02:00
|
|
|
gMonSpritesGfxPtr->sprites.ptr[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;
|
2021-10-04 16:21:03 +02:00
|
|
|
LZDecompressWram(lzPaletteData, gBattleStruct->castformPalette[CASTFORM_NORMAL]);
|
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
|
|
|
|
2021-01-23 05:22:37 +01:00
|
|
|
if (ShouldIgnoreDeoxysForm(1, battlerId) == TRUE || gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies != SPECIES_NONE)
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
|
|
|
HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonBackPicTable[species],
|
2020-09-19 19:37:24 +02:00
|
|
|
gMonSpritesGfxPtr->sprites.ptr[position],
|
2017-11-04 16:11:13 +01:00
|
|
|
species, currentPersonality);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
HandleLoadSpecialPokePic(&gMonBackPicTable[species],
|
2020-09-19 19:37:24 +02:00
|
|
|
gMonSpritesGfxPtr->sprites.ptr[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;
|
2021-10-04 16:21:03 +02:00
|
|
|
LZDecompressWram(lzPaletteData, gBattleStruct->castformPalette[CASTFORM_NORMAL]);
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-23 02:03:21 +01:00
|
|
|
// Unused
|
|
|
|
static void BattleGfxSfxDummy1(void)
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-01-23 02:03:21 +01:00
|
|
|
void BattleGfxSfxDummy2(u16 species)
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
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],
|
2020-09-19 19:37:24 +02:00
|
|
|
gMonSpritesGfxPtr->sprites.ptr[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],
|
2020-09-19 19:37:24 +02:00
|
|
|
gMonSpritesGfxPtr->sprites.ptr[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
|
|
|
}
|
|
|
|
|
2021-01-23 02:03:21 +01:00
|
|
|
void BattleGfxSfxDummy3(u8 gender)
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
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]);
|
2018-12-25 18:50:15 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2021-10-04 16:21:03 +02:00
|
|
|
void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool8 castform)
|
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
|
|
|
|
2021-10-04 16:21:03 +02:00
|
|
|
if (castform)
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
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);
|
|
|
|
}
|
2021-07-07 15:11:52 +02:00
|
|
|
gSprites[gBattlerSpriteIds[battlerAtk]].y = GetBattlerSpriteDefault_Y(battlerAtk);
|
2017-11-04 16:11:13 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const void *src;
|
|
|
|
void *dst;
|
|
|
|
u16 targetSpecies;
|
|
|
|
|
|
|
|
if (IsContest())
|
|
|
|
{
|
2021-10-03 05:47:59 +02:00
|
|
|
position = B_POSITION_PLAYER_LEFT;
|
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],
|
2021-10-03 05:47:59 +02:00
|
|
|
gMonSpritesGfxPtr->sprites.ptr[position],
|
2017-11-04 16:11:13 +01:00
|
|
|
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],
|
2020-09-19 19:37:24 +02:00
|
|
|
gMonSpritesGfxPtr->sprites.ptr[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],
|
2020-09-19 19:37:24 +02:00
|
|
|
gMonSpritesGfxPtr->sprites.ptr[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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-19 19:37:24 +02:00
|
|
|
src = gMonSpritesGfxPtr->sprites.ptr[position];
|
2020-09-02 20:14:29 +02:00
|
|
|
dst = (void *)(OBJ_VRAM0 + gSprites[gBattlerSpriteIds[battlerAtk]].oam.tileNum * 32);
|
2021-03-29 15:38:19 +02:00
|
|
|
DmaCopy32(3, src, dst, MON_PIC_SIZE);
|
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];
|
2021-10-04 16:21:03 +02:00
|
|
|
LZDecompressWram(lzPaletteData, gBattleStruct->castformPalette[CASTFORM_NORMAL]);
|
|
|
|
LoadPalette(gBattleStruct->castformPalette[gBattleMonForms[battlerDef]], 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
|
|
|
}
|
|
|
|
|
2021-07-07 15:11:52 +02:00
|
|
|
gSprites[gBattlerSpriteIds[battlerAtk]].y = GetBattlerSpriteDefault_Y(battlerAtk);
|
2018-06-19 00:43:15 +02:00
|
|
|
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())
|
2021-10-03 05:47:59 +02:00
|
|
|
position = B_POSITION_PLAYER_LEFT;
|
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())
|
2021-01-04 16:14:01 +01:00
|
|
|
LZDecompressVram(gSubstituteDollBackGfx, gMonSpritesGfxPtr->sprites.ptr[position]);
|
2018-02-08 12:13:29 +01:00
|
|
|
else if (GetBattlerSide(battlerId) != B_SIDE_PLAYER)
|
2021-01-04 16:14:01 +01:00
|
|
|
LZDecompressVram(gSubstituteDollFrontGfx, gMonSpritesGfxPtr->sprites.ptr[position]);
|
2017-11-04 16:11:13 +01:00
|
|
|
else
|
2021-01-04 16:14:01 +01:00
|
|
|
LZDecompressVram(gSubstituteDollBackGfx, gMonSpritesGfxPtr->sprites.ptr[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
|
|
|
{
|
2021-03-29 15:38:19 +02:00
|
|
|
Dma3CopyLarge32_(gMonSpritesGfxPtr->sprites.ptr[position], &gMonSpritesGfxPtr->sprites.byte[position][MON_PIC_SIZE * i], MON_PIC_SIZE);
|
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
|
|
|
}
|
Undo PokeCodec's PRs
This commit undoes most of PokeCodec's PRs after the debate in chat. Some
harmless or completely superseded PRs have been left alone, as there is not
much benefit in attempting to undo them.
Reverts #1104, #1108, #1115, #1118, #1119, #1124, #1126, #1127, #1132, #1136,
#1137, #1139, #1140, #1144, #1148, #1149, #1150, #1153, #1155, #1177, #1179,
#1180, #1181, #1182 and #1183.
2020-09-13 09:22:50 +02:00
|
|
|
else
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
Undo PokeCodec's PRs
This commit undoes most of PokeCodec's PRs after the debate in chat. Some
harmless or completely superseded PRs have been left alone, as there is not
much benefit in attempting to undo them.
Reverts #1104, #1108, #1115, #1118, #1119, #1124, #1126, #1127, #1132, #1136,
#1137, #1139, #1140, #1144, #1148, #1149, #1150, #1153, #1155, #1177, #1179,
#1180, #1181, #1182 and #1183.
2020-09-13 09:22:50 +02:00
|
|
|
if (!IsContest())
|
|
|
|
{
|
|
|
|
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)
|
2021-07-07 15:11:52 +02:00
|
|
|
gSprites[spriteId].y = GetSubstituteSpriteDefault_Y(battlerId);
|
2017-11-04 16:11:13 +01:00
|
|
|
else
|
2021-07-07 15:11:52 +02:00
|
|
|
gSprites[spriteId].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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-23 02:03:21 +01:00
|
|
|
void SetBattlerSpriteAffineMode(u8 affineMode)
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2021-07-07 15:11:52 +02:00
|
|
|
shadowSprite->x = battlerSprite->x;
|
|
|
|
shadowSprite->x2 = battlerSprite->x2;
|
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)
|
|
|
|
{
|
2018-09-10 17:25:58 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2021-09-24 20:30:15 +02:00
|
|
|
// Color the background tiles surrounding the action selection and move windows
|
|
|
|
void FillAroundBattleWindows(void)
|
2017-11-04 16:11:13 +01:00
|
|
|
{
|
|
|
|
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
|
|
|
{
|
2020-09-19 19:37:24 +02:00
|
|
|
gMonSpritesGfxPtr->sprites.ptr[i] = gMonSpritesGfxPtr->firstDecompressed + (i * 0x2000);
|
2021-01-23 05:22:37 +01:00
|
|
|
*(gMonSpritesGfxPtr->templates + i) = gBattlerSpriteTemplates[i];
|
2017-11-04 16:11:13 +01:00
|
|
|
|
|
|
|
for (j = 0; j < 4; j++)
|
|
|
|
{
|
2021-10-03 05:47:59 +02:00
|
|
|
gMonSpritesGfxPtr->frameImages[i][j].data = gMonSpritesGfxPtr->sprites.ptr[i] + (j * MON_PIC_SIZE);
|
|
|
|
gMonSpritesGfxPtr->frameImages[i][j].size = MON_PIC_SIZE;
|
2017-11-04 16:11:13 +01:00
|
|
|
}
|
|
|
|
|
2021-10-03 05:47:59 +02:00
|
|
|
gMonSpritesGfxPtr->templates[i].images = gMonSpritesGfxPtr->frameImages[i];
|
2017-11-04 16:11:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
gMonSpritesGfxPtr->barFontGfx = AllocZeroed(0x1000);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FreeMonSpritesGfx(void)
|
|
|
|
{
|
|
|
|
if (gMonSpritesGfxPtr == NULL)
|
|
|
|
return;
|
|
|
|
|
2021-10-03 05:47:59 +02:00
|
|
|
TRY_FREE_AND_SET_NULL(gMonSpritesGfxPtr->buffer);
|
|
|
|
TRY_FREE_AND_SET_NULL(gMonSpritesGfxPtr->unusedPtr);
|
2017-11-04 16:11:13 +01:00
|
|
|
FREE_AND_SET_NULL(gMonSpritesGfxPtr->barFontGfx);
|
|
|
|
FREE_AND_SET_NULL(gMonSpritesGfxPtr->firstDecompressed);
|
2021-10-03 05:47:59 +02:00
|
|
|
gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_LEFT] = NULL;
|
|
|
|
gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT] = NULL;
|
|
|
|
gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_RIGHT] = NULL;
|
|
|
|
gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_RIGHT] = NULL;
|
2017-11-04 16:11:13 +01:00
|
|
|
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;
|
|
|
|
}
|