407 lines
11 KiB
C
407 lines
11 KiB
C
#include "global.h"
|
|
#include "graphics.h"
|
|
#include "mail.h"
|
|
#include "palette.h"
|
|
#include "pokemon_sprite_visualizer.h"
|
|
#include "pokemon_icon.h"
|
|
#include "sprite.h"
|
|
#include "data.h"
|
|
#include "constants/pokemon_icon.h"
|
|
|
|
struct MonIconSpriteTemplate
|
|
{
|
|
const struct OamData *oam;
|
|
const u8 *image;
|
|
const union AnimCmd *const *anims;
|
|
const union AffineAnimCmd *const *affineAnims;
|
|
void (*callback)(struct Sprite *);
|
|
u16 paletteTag;
|
|
};
|
|
|
|
static u8 CreateMonIconSprite(struct MonIconSpriteTemplate *, s16, s16, u8);
|
|
static void FreeAndDestroyMonIconSprite_(struct Sprite *sprite);
|
|
|
|
const struct SpritePalette gMonIconPaletteTable[] =
|
|
{
|
|
{ gMonIconPalettes[0], POKE_ICON_BASE_PAL_TAG + 0 },
|
|
{ gMonIconPalettes[1], POKE_ICON_BASE_PAL_TAG + 1 },
|
|
{ gMonIconPalettes[2], POKE_ICON_BASE_PAL_TAG + 2 },
|
|
{ gMonIconPalettes[3], POKE_ICON_BASE_PAL_TAG + 3 },
|
|
{ gMonIconPalettes[4], POKE_ICON_BASE_PAL_TAG + 4 },
|
|
{ gMonIconPalettes[5], POKE_ICON_BASE_PAL_TAG + 5 },
|
|
};
|
|
|
|
static const struct OamData sMonIconOamData =
|
|
{
|
|
.y = 0,
|
|
.affineMode = ST_OAM_AFFINE_OFF,
|
|
.objMode = ST_OAM_OBJ_NORMAL,
|
|
.bpp = ST_OAM_4BPP,
|
|
.shape = SPRITE_SHAPE(32x32),
|
|
.x = 0,
|
|
.size = SPRITE_SIZE(32x32),
|
|
.tileNum = 0,
|
|
.priority = 1,
|
|
.paletteNum = 0,
|
|
};
|
|
|
|
// fastest to slowest
|
|
|
|
static const union AnimCmd sAnim_0[] =
|
|
{
|
|
ANIMCMD_FRAME(0, 6),
|
|
ANIMCMD_FRAME(1, 6),
|
|
ANIMCMD_JUMP(0),
|
|
};
|
|
|
|
static const union AnimCmd sAnim_1[] =
|
|
{
|
|
ANIMCMD_FRAME(0, 8),
|
|
ANIMCMD_FRAME(1, 8),
|
|
ANIMCMD_JUMP(0),
|
|
};
|
|
|
|
static const union AnimCmd sAnim_2[] =
|
|
{
|
|
ANIMCMD_FRAME(0, 14),
|
|
ANIMCMD_FRAME(1, 14),
|
|
ANIMCMD_JUMP(0),
|
|
};
|
|
|
|
static const union AnimCmd sAnim_3[] =
|
|
{
|
|
ANIMCMD_FRAME(0, 22),
|
|
ANIMCMD_FRAME(1, 22),
|
|
ANIMCMD_JUMP(0),
|
|
};
|
|
|
|
static const union AnimCmd sAnim_4[] =
|
|
{
|
|
ANIMCMD_FRAME(0, 29),
|
|
ANIMCMD_FRAME(0, 29), // frame 0 is repeated
|
|
ANIMCMD_JUMP(0),
|
|
};
|
|
|
|
static const union AnimCmd *const sMonIconAnims[] =
|
|
{
|
|
sAnim_0,
|
|
sAnim_1,
|
|
sAnim_2,
|
|
sAnim_3,
|
|
sAnim_4,
|
|
};
|
|
|
|
static const union AffineAnimCmd sAffineAnim_0[] =
|
|
{
|
|
AFFINEANIMCMD_FRAME(0, 0, 0, 10),
|
|
AFFINEANIMCMD_END,
|
|
};
|
|
|
|
static const union AffineAnimCmd sAffineAnim_1[] =
|
|
{
|
|
AFFINEANIMCMD_FRAME(-2, -2, 0, 122),
|
|
AFFINEANIMCMD_END,
|
|
};
|
|
|
|
static const union AffineAnimCmd *const sMonIconAffineAnims[] =
|
|
{
|
|
sAffineAnim_0,
|
|
sAffineAnim_1,
|
|
};
|
|
|
|
static const u16 sSpriteImageSizes[3][4] =
|
|
{
|
|
[ST_OAM_SQUARE] =
|
|
{
|
|
[SPRITE_SIZE(8x8)] = 8 * 8 / 2,
|
|
[SPRITE_SIZE(16x16)] = 16 * 16 / 2,
|
|
[SPRITE_SIZE(32x32)] = 32 * 32 / 2,
|
|
[SPRITE_SIZE(64x64)] = 64 * 64 / 2,
|
|
},
|
|
[ST_OAM_H_RECTANGLE] =
|
|
{
|
|
[SPRITE_SIZE(16x8)] = 16 * 8 / 2,
|
|
[SPRITE_SIZE(32x8)] = 32 * 8 / 2,
|
|
[SPRITE_SIZE(32x16)] = 32 * 16 / 2,
|
|
[SPRITE_SIZE(64x32)] = 64 * 32 / 2,
|
|
},
|
|
[ST_OAM_V_RECTANGLE] =
|
|
{
|
|
[SPRITE_SIZE(8x16)] = 8 * 16 / 2,
|
|
[SPRITE_SIZE(8x32)] = 8 * 32 / 2,
|
|
[SPRITE_SIZE(16x32)] = 16 * 32 / 2,
|
|
[SPRITE_SIZE(32x64)] = 32 * 64 / 2,
|
|
},
|
|
};
|
|
|
|
u8 CreateMonIcon(u16 species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority, u32 personality)
|
|
{
|
|
u8 spriteId;
|
|
struct MonIconSpriteTemplate iconTemplate =
|
|
{
|
|
.oam = &sMonIconOamData,
|
|
.image = GetMonIconPtr(species, personality),
|
|
.anims = sMonIconAnims,
|
|
.affineAnims = sMonIconAffineAnims,
|
|
.callback = callback,
|
|
.paletteTag = POKE_ICON_BASE_PAL_TAG + gSpeciesInfo[species].iconPalIndex,
|
|
};
|
|
species = SanitizeSpeciesId(species);
|
|
|
|
if (species > NUM_SPECIES)
|
|
iconTemplate.paletteTag = POKE_ICON_BASE_PAL_TAG;
|
|
#if P_GENDER_DIFFERENCES
|
|
else if (gSpeciesInfo[species].iconSpriteFemale != NULL && IsPersonalityFemale(species, personality))
|
|
iconTemplate.paletteTag = POKE_ICON_BASE_PAL_TAG + gSpeciesInfo[species].iconPalIndexFemale;
|
|
#endif
|
|
|
|
spriteId = CreateMonIconSprite(&iconTemplate, x, y, subpriority);
|
|
|
|
UpdateMonIconFrame(&gSprites[spriteId]);
|
|
|
|
return spriteId;
|
|
}
|
|
|
|
|
|
u8 CreateMonIconNoPersonality(u16 species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority)
|
|
{
|
|
u8 spriteId;
|
|
struct MonIconSpriteTemplate iconTemplate =
|
|
{
|
|
.oam = &sMonIconOamData,
|
|
.image = NULL,
|
|
.anims = sMonIconAnims,
|
|
.affineAnims = sMonIconAffineAnims,
|
|
.callback = callback,
|
|
.paletteTag = POKE_ICON_BASE_PAL_TAG + gSpeciesInfo[species].iconPalIndex,
|
|
};
|
|
|
|
iconTemplate.image = GetMonIconTiles(species, 0);
|
|
spriteId = CreateMonIconSprite(&iconTemplate, x, y, subpriority);
|
|
|
|
UpdateMonIconFrame(&gSprites[spriteId]);
|
|
|
|
return spriteId;
|
|
}
|
|
|
|
u16 GetIconSpecies(u16 species, u32 personality)
|
|
{
|
|
species = SanitizeSpeciesId(species);
|
|
if (species == SPECIES_UNOWN)
|
|
species = GetUnownSpeciesId(personality);
|
|
return species;
|
|
}
|
|
|
|
u16 GetUnownLetterByPersonality(u32 personality)
|
|
{
|
|
if (!personality)
|
|
return 0;
|
|
else
|
|
return GET_UNOWN_LETTER(personality);
|
|
}
|
|
|
|
u16 GetIconSpeciesNoPersonality(u16 species)
|
|
{
|
|
species = SanitizeSpeciesId(species);
|
|
|
|
if (MailSpeciesToSpecies(species, &species) == SPECIES_UNOWN)
|
|
return species += SPECIES_UNOWN_B; // TODO
|
|
return GetIconSpecies(species, 0);
|
|
}
|
|
|
|
const u8 *GetMonIconPtr(u16 species, u32 personality)
|
|
{
|
|
return GetMonIconTiles(GetIconSpecies(species, personality), personality);
|
|
}
|
|
|
|
void FreeAndDestroyMonIconSprite(struct Sprite *sprite)
|
|
{
|
|
FreeAndDestroyMonIconSprite_(sprite);
|
|
}
|
|
|
|
void LoadMonIconPalettes(void)
|
|
{
|
|
u8 i;
|
|
for (i = 0; i < ARRAY_COUNT(gMonIconPaletteTable); i++)
|
|
LoadSpritePalette(&gMonIconPaletteTable[i]);
|
|
}
|
|
|
|
// unused
|
|
void SafeLoadMonIconPalette(u16 species)
|
|
{
|
|
u8 palIndex;
|
|
palIndex = gSpeciesInfo[SanitizeSpeciesId(species)].iconPalIndex;
|
|
if (IndexOfSpritePaletteTag(gMonIconPaletteTable[palIndex].tag) == 0xFF)
|
|
LoadSpritePalette(&gMonIconPaletteTable[palIndex]);
|
|
}
|
|
|
|
void LoadMonIconPalette(u16 species)
|
|
{
|
|
u8 palIndex = gSpeciesInfo[SanitizeSpeciesId(species)].iconPalIndex;
|
|
if (IndexOfSpritePaletteTag(gMonIconPaletteTable[palIndex].tag) == 0xFF)
|
|
LoadSpritePalette(&gMonIconPaletteTable[palIndex]);
|
|
}
|
|
|
|
void LoadMonIconPalettePersonality(u16 species, u32 personality)
|
|
{
|
|
u8 palIndex;
|
|
species = SanitizeSpeciesId(species);
|
|
#if P_GENDER_DIFFERENCES
|
|
if (gSpeciesInfo[species].iconSpriteFemale != NULL && IsPersonalityFemale(species, personality))
|
|
palIndex = gSpeciesInfo[species].iconPalIndexFemale;
|
|
else
|
|
#endif
|
|
palIndex = gSpeciesInfo[species].iconPalIndex;
|
|
if (IndexOfSpritePaletteTag(gMonIconPaletteTable[palIndex].tag) == 0xFF)
|
|
LoadSpritePalette(&gMonIconPaletteTable[palIndex]);
|
|
}
|
|
|
|
void FreeMonIconPalettes(void)
|
|
{
|
|
u8 i;
|
|
for (i = 0; i < ARRAY_COUNT(gMonIconPaletteTable); i++)
|
|
FreeSpritePaletteByTag(gMonIconPaletteTable[i].tag);
|
|
}
|
|
|
|
// unused
|
|
void SafeFreeMonIconPalette(u16 species)
|
|
{
|
|
u8 palIndex;
|
|
palIndex = gSpeciesInfo[SanitizeSpeciesId(species)].iconPalIndex;
|
|
FreeSpritePaletteByTag(gMonIconPaletteTable[palIndex].tag);
|
|
}
|
|
|
|
void FreeMonIconPalette(u16 species)
|
|
{
|
|
u8 palIndex;
|
|
palIndex = gSpeciesInfo[SanitizeSpeciesId(species)].iconPalIndex;
|
|
FreeSpritePaletteByTag(gMonIconPaletteTable[palIndex].tag);
|
|
}
|
|
|
|
void SpriteCB_MonIcon(struct Sprite *sprite)
|
|
{
|
|
UpdateMonIconFrame(sprite);
|
|
}
|
|
|
|
const u8 *GetMonIconTiles(u16 species, u32 personality)
|
|
{
|
|
const u8 *iconSprite;
|
|
|
|
if (species > NUM_SPECIES)
|
|
species = SPECIES_NONE;
|
|
|
|
#if P_GENDER_DIFFERENCES
|
|
if (gSpeciesInfo[species].iconSpriteFemale != NULL && IsPersonalityFemale(species, personality))
|
|
iconSprite = gSpeciesInfo[species].iconSpriteFemale;
|
|
else
|
|
#endif
|
|
if (gSpeciesInfo[species].iconSprite != NULL)
|
|
iconSprite = gSpeciesInfo[species].iconSprite;
|
|
else
|
|
iconSprite = gSpeciesInfo[SPECIES_NONE].iconSprite;
|
|
|
|
return iconSprite;
|
|
}
|
|
|
|
void TryLoadAllMonIconPalettesAtOffset(u16 offset)
|
|
{
|
|
s32 i;
|
|
if (offset <= BG_PLTT_ID(16 - ARRAY_COUNT(gMonIconPaletteTable)))
|
|
{
|
|
for (i = 0; i < (int)ARRAY_COUNT(gMonIconPaletteTable); i++)
|
|
{
|
|
LoadPalette(gMonIconPaletteTable[i].data, offset, PLTT_SIZE_4BPP);
|
|
offset += 16;
|
|
}
|
|
}
|
|
}
|
|
|
|
u8 GetValidMonIconPalIndex(u16 species)
|
|
{
|
|
return gSpeciesInfo[SanitizeSpeciesId(species)].iconPalIndex;
|
|
}
|
|
|
|
u8 GetMonIconPaletteIndexFromSpecies(u16 species)
|
|
{
|
|
return gSpeciesInfo[SanitizeSpeciesId(species)].iconPalIndex;
|
|
}
|
|
|
|
const u16 *GetValidMonIconPalettePtr(u16 species)
|
|
{
|
|
return gMonIconPaletteTable[gSpeciesInfo[SanitizeSpeciesId(species)].iconPalIndex].data;
|
|
}
|
|
|
|
u8 UpdateMonIconFrame(struct Sprite *sprite)
|
|
{
|
|
u8 result = 0;
|
|
|
|
if (sprite->animDelayCounter == 0)
|
|
{
|
|
s16 frame = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.imageValue;
|
|
|
|
switch (frame)
|
|
{
|
|
case -1:
|
|
break;
|
|
case -2:
|
|
sprite->animCmdIndex = 0;
|
|
break;
|
|
default:
|
|
RequestSpriteCopy(
|
|
// pointer arithmetic is needed to get the correct pointer to perform the sprite copy on.
|
|
// because sprite->images is a struct def, it has to be casted to (u8 *) before any
|
|
// arithmetic can be performed.
|
|
(u8 *)sprite->images + (sSpriteImageSizes[sprite->oam.shape][sprite->oam.size] * frame),
|
|
(u8 *)(OBJ_VRAM0 + sprite->oam.tileNum * TILE_SIZE_4BPP),
|
|
sSpriteImageSizes[sprite->oam.shape][sprite->oam.size]);
|
|
sprite->animDelayCounter = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.duration & 0xFF;
|
|
sprite->animCmdIndex++;
|
|
result = sprite->animCmdIndex;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sprite->animDelayCounter--;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static u8 CreateMonIconSprite(struct MonIconSpriteTemplate *iconTemplate, s16 x, s16 y, u8 subpriority)
|
|
{
|
|
u8 spriteId;
|
|
|
|
struct SpriteFrameImage image = { NULL, sSpriteImageSizes[iconTemplate->oam->shape][iconTemplate->oam->size] };
|
|
|
|
struct SpriteTemplate spriteTemplate =
|
|
{
|
|
.tileTag = TAG_NONE,
|
|
.paletteTag = iconTemplate->paletteTag,
|
|
.oam = iconTemplate->oam,
|
|
.anims = iconTemplate->anims,
|
|
.images = &image,
|
|
.affineAnims = iconTemplate->affineAnims,
|
|
.callback = iconTemplate->callback,
|
|
};
|
|
|
|
spriteId = CreateSprite(&spriteTemplate, x, y, subpriority);
|
|
gSprites[spriteId].animPaused = TRUE;
|
|
gSprites[spriteId].animBeginning = FALSE;
|
|
gSprites[spriteId].images = (const struct SpriteFrameImage *)iconTemplate->image;
|
|
return spriteId;
|
|
}
|
|
|
|
static void FreeAndDestroyMonIconSprite_(struct Sprite *sprite)
|
|
{
|
|
struct SpriteFrameImage image = { NULL, sSpriteImageSizes[sprite->oam.shape][sprite->oam.size] };
|
|
sprite->images = ℑ
|
|
DestroySprite(sprite);
|
|
}
|
|
|
|
void SetPartyHPBarSprite(struct Sprite *sprite, u8 animNum)
|
|
{
|
|
sprite->animNum = animNum;
|
|
sprite->animDelayCounter = 0;
|
|
sprite->animCmdIndex = 0;
|
|
}
|