sovereignx/src/trainer_pokemon_sprites.c
Eduardo Quezada D'Ottone 4adc2dcb16
Species Simplifier™ - Part 3 (#3562)
* Added SpeciesInfo fields

# Conflicts:
#	include/pokemon.h

* Added missing comments

* Renamed gigantamax to isGigantamax

* Converted species flags to agbcc bit flags

* Added padding after flags

* Pikachu form config

* Dex text

* Reordered Paradox flag

* Missing Pikachu ifdef comments

* Moved P_GEN_x_POKEMON settings to the species_families file

* Gen 1 Dex entries

* Renamed file to species_enabled.h

* Prevent Pokémon from evolving if their evolution is disabled

* Prevent Pokémon from being affected by Eviolite if their evolution is disabled

* Prevent Pokémon offspring if they're disabled

* Corrected imprementation of evolution prevention

It could potentially overwrite items by accident

* Cross-evo configs

* Gen 2 dex entries

* Changed cry table to use assignable IDs

# Conflicts:
#	include/pokemon.h

* Form table pointers

* Beginning support for moving data to gSpeciesInfo

* Pokédexes reads text from gSpeciesInfo

* Reading species names from gSpeciesInfo

* Fixed erroneous copy-paste

* Moved Bulbasaur to Raichu Family data do gSpeciesinfo

* Added female pic sizes

* Macros for Front, Back, Palette and Learnsets

* Sandshrew to Dugtrio Families

* Obtains Height/Weight from gSpeciesInfo

* Read category from gSpeciesInfo

* Removed unused data from pokedex_entries.h

* Moved Gen 1 data to gSpeciesInfo

* Moved Gen 2 data to gSpeciesInfo + fixed Ursaluna Bloodmoon not producing Teddiursa eggs

* Moved Gen 3 data to gSpeciesInfo

* Moved Gen 4 data to gSpeciesInfo

* HGSS dex properly shows form sprites

* Fixed data type for GetSpeciesHeight/Weight

* Reading Pokédex Size data from gSpeciesInfo

* Cleaned up mon graphic decompression function

* Reading Front Pics gSpeciesInfo

* Reading Back Pics gSpeciesInfo

* Updated uses of GetMonSpritePalStruct to allow loading the data directly instead of reading the struct

* Reading palettes from gSpeciesInfo

* Reading animation delay from gSpeciesInfo

* Fixed Pokémon Debug Menu not reading animation delay

* Reading front anim Id from gSpeciesInfo

* Reading back anim Id from gSpeciesInfo

* Reading Animation Frames from gSpeciesInfo

* Reading Icon Sprites from gSpeciesInfo

* Reading Icon Palette IDs from gSpeciesInfo

* Reading Footprints from gSpeciesInfo

* Reading Mon Pic sizes from gSpeciesInfo

* Separate mon pic sizes for female mon

* Reading Level Up Learnsets from gSpeciesInfo

* Reading Teachable Learnsets from gSpeciesInfo

* Reading National Dex Number from gSpeciesInfo

* Reading Enemy Mon Elevation from gSpeciesInfo

* Reading Evolutions from gSpeciesInfo

* Reading form table from gSpeciesInfo

* Fixed button label inconsistency in pokémon debug menu

* Reading form change table from gSpeciesInfo

* Removed need to define mon graphics in include/graphics.h

* Reordered mon graphics by family

* Fixed National dex number offset

* gFrontierBannedSpecies now checks IsSpeciesEnabled

* Added 3 more toggles for Fusions, Primal Reversions and Ultra Burst

* Gen 3 & 4 family toggles for dex entries

* Fixed missing Mr. Rime data

* Gen 1 dex descriptions as compound strings

* Gen 2 dex descriptions as compound strings

* Gen 3 dex descriptions as compound strings

* Gen 4 dex descriptions as compound strings

* Fixed compile in agbcc

* Moved Gen 5 data to gSpeciesInfo

* Using PLACEHOLDER_ANIM_SINGLE_FRAME when needed (same hash)

* Renamed PLACEHOLDER_TWO_FRAME_ANIMATION to PLACEHOLDER_ANIM_TWO_FRAMES

* Fixed capitalization for front pic anims

* Fixed `CanEvolve`

* Moved Gen 6 data to gSpeciesInfo

* Gen 7 without macros

* Gen 8 without macros

* Gen 9 without macros

* Fixed Gen 9 sound data

* Finished moving Gen 7 data in macros (by Alex)

Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>

* Ultra Necrozma is now included in the fusion forms define

* Cries are now properly excluded from the rom when disabling species

* Removed P_GEN_x_POKEMON from form_change_tables.h

* Fixed Yanmega's cry ignoring the P_GEN_4_CROSS_EVOS setting

* Added P_NEW_EVOS_IN_REGIONAL_DEX setting

* Automatic ASSUMPTION_FAIL when used species are disabled

* Finished moving Gen 8 data in macros (by Alex)

Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>

* Expanded Alcremie macro

* Finished moving Gen 9 data in macros (by Alex)

* Fixed missing data for Komala and Marshadow

* Form species id tables use family toggles + added missing Ursaluna form species id table

* Fixed Genesect palettes

* Fixed Flabébé family graphics

* Fixed Minior Graphics

* Fixed missing Calyrex data

* Family toggles in mon graphcis (By Jasper/Bassoonian)

Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>

* Fixed missing Ogerpon data

* Ordered Level Up Learnsets (missing toggles)

Also added White Basculin learnset

* Added more Minior synonyms

* Fixed enamorus order

* Reordered teachable learnsets

* Removed sSpeciesXXX level up learnsets + reordered

* Removed unneeded assumes

* Removed unused extra animations

* Family toggles in mon level up learnsets (By Jasper/Bassoonian)

Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>

* Fixed Phione graphics inclusion

* Family toggles for Teachable Learnsets

Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>

* Ordered Front Pic Anims

* Family toggles for front pic animations

Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>

* Fixed HGSS dex incorrectly showing the wrong mon when catching it

* Family toggles for Egg Moves + reodered

Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>

* Fixed HGSS not checking for null footprints

* Review changes

* Fixed Female difference mon not using their macros

* Fixed Alcremie Macro

* Fixed compile error when disabling the Bulbasaur family

* Fixed Turtwig and Chimchar family + Houndour and Mareep cries not being excluded properly

* Re-added missing Egg graphical data

* Fixed crash during the Birch Intro when Lotad is disabled

* Renamed PALLETE to PALETTES

* Removed extra spacing for YOffsets

* Fixed compile when only disabling cross-gen evolutions

* Added Tera Forms define (Ogerpon and Terapagos)

* Fixed Necrozma macro

* Removed .noFlip = FALSE

* Fixed dex number in summary screen for forms when nat dex is disabled

* Fixed Paldean form paths

---------

Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>
Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>
2023-12-08 15:05:10 +01:00

354 lines
11 KiB
C

#include "global.h"
#include "sprite.h"
#include "window.h"
#include "malloc.h"
#include "palette.h"
#include "decompress.h"
#include "trainer_pokemon_sprites.h"
#include "data.h"
#include "pokemon.h"
#include "constants/trainers.h"
#define PICS_COUNT 8
// Needs to be large enough to store either a decompressed pokemon pic or trainer pic
#define PIC_SPRITE_SIZE max(MON_PIC_SIZE, TRAINER_PIC_SIZE)
#define MAX_PIC_FRAMES max(MAX_MON_PIC_FRAMES, MAX_TRAINER_PIC_FRAMES)
struct PicData
{
u8 *frames;
struct SpriteFrameImage *images;
u16 paletteTag;
u8 spriteId;
u8 active;
};
static EWRAM_DATA struct SpriteTemplate sCreatingSpriteTemplate = {};
static EWRAM_DATA struct PicData sSpritePics[PICS_COUNT] = {};
static const struct PicData sDummyPicData = {};
static const struct OamData sOamData_Normal =
{
.shape = SPRITE_SHAPE(64x64),
.size = SPRITE_SIZE(64x64)
};
static const struct OamData sOamData_Affine =
{
.affineMode = ST_OAM_AFFINE_NORMAL,
.shape = SPRITE_SHAPE(64x64),
.size = SPRITE_SIZE(64x64)
};
static void DummyPicSpriteCallback(struct Sprite *sprite)
{
}
bool16 ResetAllPicSprites(void)
{
int i;
for (i = 0; i < PICS_COUNT; i ++)
sSpritePics[i] = sDummyPicData;
return FALSE;
}
static bool16 DecompressPic(u16 species, u32 personality, bool8 isFrontPic, u8 *dest, bool8 isTrainer)
{
if (!isTrainer)
{
LoadSpecialPokePic(dest, species, personality, isFrontPic);
}
else
{
if (isFrontPic)
DecompressPicFromTable(&gTrainerFrontPicTable[species], dest);
else
DecompressPicFromTable(&gTrainerBackPicTable[species], dest);
}
return FALSE;
}
static void LoadPicPaletteByTagOrSlot(u16 species, u32 otId, u32 personality, u8 paletteSlot, u16 paletteTag, bool8 isTrainer)
{
if (!isTrainer)
{
if (paletteTag == TAG_NONE)
{
sCreatingSpriteTemplate.paletteTag = TAG_NONE;
LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality), OBJ_PLTT_ID(paletteSlot), PLTT_SIZE_4BPP);
}
else
{
sCreatingSpriteTemplate.paletteTag = paletteTag;
LoadCompressedSpritePaletteWithTag(GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality), species);
}
}
else
{
if (paletteTag == TAG_NONE)
{
sCreatingSpriteTemplate.paletteTag = TAG_NONE;
LoadCompressedPalette(gTrainerFrontPicPaletteTable[species].data, OBJ_PLTT_ID(paletteSlot), PLTT_SIZE_4BPP);
}
else
{
sCreatingSpriteTemplate.paletteTag = paletteTag;
LoadCompressedSpritePalette(&gTrainerFrontPicPaletteTable[species]);
}
}
}
static void LoadPicPaletteBySlot(u16 species, u32 otId, u32 personality, u8 paletteSlot, bool8 isTrainer)
{
if (!isTrainer)
LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality), PLTT_ID(paletteSlot), PLTT_SIZE_4BPP);
else
LoadCompressedPalette(gTrainerFrontPicPaletteTable[species].data, PLTT_ID(paletteSlot), PLTT_SIZE_4BPP);
}
static void AssignSpriteAnimsTable(bool8 isTrainer)
{
if (!isTrainer)
sCreatingSpriteTemplate.anims = gAnims_MonPic;
else
sCreatingSpriteTemplate.anims = gTrainerFrontAnimsPtrTable[0];
}
static u16 CreatePicSprite(u16 species, u32 otId, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag, bool8 isTrainer)
{
u8 i;
u8 *framePics;
struct SpriteFrameImage *images;
int j;
u8 spriteId;
for (i = 0; i < PICS_COUNT; i ++)
{
if (!sSpritePics[i].active)
break;
}
if (i == PICS_COUNT)
return 0xFFFF;
framePics = Alloc(PIC_SPRITE_SIZE * MAX_PIC_FRAMES);
if (!framePics)
return 0xFFFF;
images = Alloc(sizeof(struct SpriteFrameImage) * MAX_PIC_FRAMES);
if (!images)
{
Free(framePics);
return 0xFFFF;
}
if (DecompressPic(species, personality, isFrontPic, framePics, isTrainer))
{
// debug trap?
return 0xFFFF;
}
for (j = 0; j < MAX_PIC_FRAMES; j ++)
{
images[j].data = framePics + PIC_SPRITE_SIZE * j;
images[j].size = PIC_SPRITE_SIZE;
}
sCreatingSpriteTemplate.tileTag = TAG_NONE;
sCreatingSpriteTemplate.oam = &sOamData_Normal;
AssignSpriteAnimsTable(isTrainer);
sCreatingSpriteTemplate.images = images;
sCreatingSpriteTemplate.affineAnims = gDummySpriteAffineAnimTable;
sCreatingSpriteTemplate.callback = DummyPicSpriteCallback;
LoadPicPaletteByTagOrSlot(species, otId, personality, paletteSlot, paletteTag, isTrainer);
spriteId = CreateSprite(&sCreatingSpriteTemplate, x, y, 0);
if (paletteTag == TAG_NONE)
gSprites[spriteId].oam.paletteNum = paletteSlot;
sSpritePics[i].frames = framePics;
sSpritePics[i].images = images;
sSpritePics[i].paletteTag = paletteTag;
sSpritePics[i].spriteId = spriteId;
sSpritePics[i].active = TRUE;
return spriteId;
}
u16 CreateMonPicSprite_Affine(u16 species, u32 otId, u32 personality, u8 flags, s16 x, s16 y, u8 paletteSlot, u16 paletteTag)
{
u8 *framePics;
struct SpriteFrameImage *images;
int j;
u8 i;
u8 spriteId;
u8 type;
species = SanitizeSpeciesId(species);
for (i = 0; i < PICS_COUNT; i++)
{
if (!sSpritePics[i].active)
break;
}
if (i == PICS_COUNT)
return 0xFFFF;
framePics = Alloc(MON_PIC_SIZE * MAX_MON_PIC_FRAMES);
if (!framePics)
return 0xFFFF;
if (flags & F_MON_PIC_NO_AFFINE)
{
flags &= ~F_MON_PIC_NO_AFFINE;
type = MON_PIC_AFFINE_NONE;
}
else
{
type = flags;
}
images = Alloc(sizeof(struct SpriteFrameImage) * MAX_MON_PIC_FRAMES);
if (!images)
{
Free(framePics);
return 0xFFFF;
}
if (DecompressPic(species, personality, flags, framePics, FALSE))
{
// debug trap?
return 0xFFFF;
}
for (j = 0; j < MAX_MON_PIC_FRAMES; j ++)
{
images[j].data = framePics + MON_PIC_SIZE * j;
images[j].size = MON_PIC_SIZE;
}
sCreatingSpriteTemplate.tileTag = TAG_NONE;
sCreatingSpriteTemplate.anims = gSpeciesInfo[species].frontAnimFrames;
sCreatingSpriteTemplate.images = images;
if (type == MON_PIC_AFFINE_FRONT)
{
sCreatingSpriteTemplate.affineAnims = gAffineAnims_BattleSpriteOpponentSide;
sCreatingSpriteTemplate.oam = &sOamData_Affine;
}
else if (type == MON_PIC_AFFINE_BACK)
{
sCreatingSpriteTemplate.affineAnims = gAffineAnims_BattleSpritePlayerSide;
sCreatingSpriteTemplate.oam = &sOamData_Affine;
}
else // MON_PIC_AFFINE_NONE
{
sCreatingSpriteTemplate.oam = &sOamData_Normal;
sCreatingSpriteTemplate.affineAnims = gDummySpriteAffineAnimTable;
}
sCreatingSpriteTemplate.callback = DummyPicSpriteCallback;
LoadPicPaletteByTagOrSlot(species, otId, personality, paletteSlot, paletteTag, FALSE);
spriteId = CreateSprite(&sCreatingSpriteTemplate, x, y, 0);
if (paletteTag == TAG_NONE)
gSprites[spriteId].oam.paletteNum = paletteSlot;
sSpritePics[i].frames = framePics;
sSpritePics[i].images = images;
sSpritePics[i].paletteTag = paletteTag;
sSpritePics[i].spriteId = spriteId;
sSpritePics[i].active = TRUE;
return spriteId;
}
static u16 FreeAndDestroyPicSpriteInternal(u16 spriteId)
{
u8 i;
u8 *framePics;
struct SpriteFrameImage *images;
for (i = 0; i < PICS_COUNT; i ++)
{
if (sSpritePics[i].spriteId == spriteId)
break;
}
if (i == PICS_COUNT)
return 0xFFFF;
framePics = sSpritePics[i].frames;
images = sSpritePics[i].images;
if (sSpritePics[i].paletteTag != TAG_NONE)
FreeSpritePaletteByTag(GetSpritePaletteTagByPaletteNum(gSprites[spriteId].oam.paletteNum));
DestroySprite(&gSprites[spriteId]);
Free(framePics);
Free(images);
sSpritePics[i] = sDummyPicData;
return 0;
}
static u16 LoadPicSpriteInWindow(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u8 paletteSlot, u8 windowId, bool8 isTrainer)
{
if (DecompressPic(species, personality, isFrontPic, (u8 *)GetWindowAttribute(windowId, WINDOW_TILE_DATA), FALSE))
return 0xFFFF;
LoadPicPaletteBySlot(species, otId, personality, paletteSlot, isTrainer);
return 0;
}
static u16 CreateTrainerCardSprite(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId, bool8 isTrainer)
{
u8 *framePics;
framePics = Alloc(TRAINER_PIC_SIZE * MAX_TRAINER_PIC_FRAMES);
if (framePics && !DecompressPic(species, personality, isFrontPic, framePics, isTrainer))
{
BlitBitmapRectToWindow(windowId, framePics, 0, 0, TRAINER_PIC_WIDTH, TRAINER_PIC_HEIGHT, destX, destY, TRAINER_PIC_WIDTH, TRAINER_PIC_HEIGHT);
LoadPicPaletteBySlot(species, otId, personality, paletteSlot, isTrainer);
Free(framePics);
return 0;
}
return 0xFFFF;
}
u16 CreateMonPicSprite(u16 species, u32 otId, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag)
{
return CreatePicSprite(species, otId, personality, isFrontPic, x, y, paletteSlot, paletteTag, FALSE);
}
u16 FreeAndDestroyMonPicSprite(u16 spriteId)
{
return FreeAndDestroyPicSpriteInternal(spriteId);
}
static u16 UNUSED LoadMonPicInWindow(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u8 paletteSlot, u8 windowId)
{
return LoadPicSpriteInWindow(species, otId, personality, isFrontPic, paletteSlot, windowId, FALSE);
}
// Unused, FRLG only
u16 CreateTrainerCardMonIconSprite(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId)
{
return CreateTrainerCardSprite(species, otId, personality, isFrontPic, destX, destY, paletteSlot, windowId, FALSE);
}
u16 CreateTrainerPicSprite(u16 species, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag)
{
return CreatePicSprite(species, 0, 0, isFrontPic, x, y, paletteSlot, paletteTag, TRUE);
}
u16 FreeAndDestroyTrainerPicSprite(u16 spriteId)
{
return FreeAndDestroyPicSpriteInternal(spriteId);
}
static u16 UNUSED LoadTrainerPicInWindow(u16 species, bool8 isFrontPic, u8 paletteSlot, u8 windowId)
{
return LoadPicSpriteInWindow(species, 0, 0, isFrontPic, paletteSlot, windowId, TRUE);
}
u16 CreateTrainerCardTrainerPicSprite(u16 species, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId)
{
return CreateTrainerCardSprite(species, 0, 0, isFrontPic, destX, destY, paletteSlot, windowId, TRUE);
}
u16 PlayerGenderToFrontTrainerPicId_Debug(u8 gender, bool8 getClass)
{
if (getClass == TRUE)
{
if (gender != MALE)
return gFacilityClassToPicIndex[FACILITY_CLASS_MAY];
else
return gFacilityClassToPicIndex[FACILITY_CLASS_BRENDAN];
}
return gender;
}