mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-11-18 20:47:40 +01:00
473 lines
13 KiB
C
473 lines
13 KiB
C
|
#include "global.h"
|
||
|
#include "pokeblock.h"
|
||
|
#include "sprite.h"
|
||
|
#include "task.h"
|
||
|
#include "palette.h"
|
||
|
#include "menu.h"
|
||
|
#include "malloc.h"
|
||
|
#include "pokemon.h"
|
||
|
#include "blend_palette.h"
|
||
|
#include "main.h"
|
||
|
#include "menu_helpers.h"
|
||
|
#include "bg.h"
|
||
|
#include "gpu_regs.h"
|
||
|
#include "data2.h"
|
||
|
#include "decompress.h"
|
||
|
#include "event_data.h"
|
||
|
#include "strings.h"
|
||
|
#include "string_util.h"
|
||
|
#include "new_menu_helpers.h"
|
||
|
#include "party_menu.h"
|
||
|
#include "m4a.h"
|
||
|
#include "sound.h"
|
||
|
#include "battle.h" // to get rid of once gMonSpritesGfxPtr is put elsewhere
|
||
|
|
||
|
struct PokeblockFeedStruct
|
||
|
{
|
||
|
u8 field_0[0x48];
|
||
|
u8 tilemapBuffer[0x1008];
|
||
|
u8 field_1050;
|
||
|
u8 field_1051;
|
||
|
u8 field_1052;
|
||
|
bool8 noMonFlip;
|
||
|
u16 species;
|
||
|
u16 field_1056;
|
||
|
u16 field_1058;
|
||
|
u8 nature;
|
||
|
u8 monSpriteId_;
|
||
|
u8 field_105C;
|
||
|
u8 monSpriteId;
|
||
|
u8 pokeblockCaseSpriteId;
|
||
|
u8 pokeblockSpriteId;
|
||
|
u8 field_1060[0x1E];
|
||
|
s16 loadGfxState;
|
||
|
u8 somefield[2];
|
||
|
};
|
||
|
|
||
|
extern u8 gPokeblockMonId;
|
||
|
extern u16 gSpecialVar_ItemId;
|
||
|
extern s16 gPokeblockGain;
|
||
|
extern struct MusicPlayerInfo gMPlay_BGM;
|
||
|
extern struct SpriteTemplate gUnknown_0202499C;
|
||
|
|
||
|
extern struct PokeblockFeedStruct *sPokeblockFeed;
|
||
|
extern struct CompressedSpritePalette sPokeblockSpritePal;
|
||
|
|
||
|
extern bool8 sub_81221EC(void);
|
||
|
extern void sub_806A068(u16, u8);
|
||
|
|
||
|
// this file's functions
|
||
|
static void HandleInitBackgrounds(void);
|
||
|
static void HandleInitWindows(void);
|
||
|
static bool8 LoadMonAndSceneGfx(struct Pokemon *mon);
|
||
|
u8 CreatePokeblockCaseSpriteForFeeding(void);
|
||
|
static u8 CreateMonSprite(struct Pokemon *mon);
|
||
|
void LaunchPokeblockFeedTask(void);
|
||
|
static void SetPokeblockSpritePal(u8 pokeblockCaseId);
|
||
|
void sub_817A5CC(void);
|
||
|
void sub_8148108(u8 spriteId, bool8 a1);
|
||
|
u8 CreatePokeblockSprite(void);
|
||
|
void DoPokeblockCaseThrowEffect(u8 spriteId, bool8 arg1);
|
||
|
static void PrepareMonToMoveToPokeblock(u8 spriteId);
|
||
|
void Task_HandleMonAtePokeblock(u8 taskId);
|
||
|
void Task_PaletteFadeToReturn(u8 taskId);
|
||
|
void sub_817A634(void);
|
||
|
static void sub_817A468(struct Sprite *sprite);
|
||
|
|
||
|
static void CB2_PokeblockFeed(void)
|
||
|
{
|
||
|
RunTasks();
|
||
|
AnimateSprites();
|
||
|
BuildOamBuffer();
|
||
|
do_scheduled_bg_tilemap_copies_to_vram();
|
||
|
UpdatePaletteFade();
|
||
|
}
|
||
|
|
||
|
static void VBlankCB_PokeblockFeed(void)
|
||
|
{
|
||
|
LoadOam();
|
||
|
ProcessSpriteCopyRequests();
|
||
|
TransferPlttBuffer();
|
||
|
}
|
||
|
|
||
|
bool8 TransitionToPokeblockFeedScene(void)
|
||
|
{
|
||
|
switch (gMain.state)
|
||
|
{
|
||
|
case 0:
|
||
|
sPokeblockFeed = AllocZeroed(sizeof(*sPokeblockFeed));
|
||
|
SetVBlankHBlankCallbacksToNull();
|
||
|
clear_scheduled_bg_copies_to_vram();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 1:
|
||
|
ResetPaletteFade();
|
||
|
gPaletteFade.bufferTransferDisabled = 1;
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 2:
|
||
|
ResetSpriteData();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 3:
|
||
|
FreeAllSpritePalettes();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 4:
|
||
|
AllocateMonSpritesGfx();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 5:
|
||
|
HandleInitBackgrounds();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 6:
|
||
|
HandleInitWindows();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 7:
|
||
|
if (LoadMonAndSceneGfx(&gPlayerParty[gPokeblockMonId]))
|
||
|
{
|
||
|
gMain.state++;
|
||
|
}
|
||
|
break;
|
||
|
case 8:
|
||
|
sPokeblockFeed->pokeblockCaseSpriteId = CreatePokeblockCaseSpriteForFeeding();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 9:
|
||
|
sPokeblockFeed->monSpriteId = CreateMonSprite(&gPlayerParty[gPokeblockMonId]);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 10:
|
||
|
SetWindowBorderStyle(0, 1, 1, 14);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 11:
|
||
|
LaunchPokeblockFeedTask();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 12:
|
||
|
BlendPalettes(-1, 0x10, 0);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 13:
|
||
|
BeginNormalPaletteFade(-1, 0, 0x10, 0, 0);
|
||
|
gPaletteFade.bufferTransferDisabled = 0;
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
default:
|
||
|
SetVBlankCallback(VBlankCB_PokeblockFeed);
|
||
|
SetMainCallback2(CB2_PokeblockFeed);
|
||
|
return TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
void CB2_PreparePokeblockFeedScene(void)
|
||
|
{
|
||
|
while (1)
|
||
|
{
|
||
|
if (sub_81221EC() == TRUE)
|
||
|
break;
|
||
|
if (TransitionToPokeblockFeedScene() == TRUE)
|
||
|
break;
|
||
|
if (sub_81221AC() == TRUE)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
extern const struct BgTemplate gUnknown_085F0550[2];
|
||
|
extern const u8 gBattleTerrainPalette_Frontier[];
|
||
|
extern const u8 gBattleTerrainTiles_Building[];
|
||
|
extern const u8 gUnknown_08D9BA44[];
|
||
|
extern const struct CompressedSpriteSheet gPokeblockCase_SpriteSheet;
|
||
|
extern const struct CompressedSpriteSheet gPokeblock_SpriteSheet;
|
||
|
extern const struct CompressedSpritePalette gPokeblockCase_SpritePal;
|
||
|
extern const struct CompressedSpriteSheet gMonFrontPicTable[];
|
||
|
extern const struct WindowTemplate gUnknown_085F0558[];
|
||
|
extern const u16 gUnknown_0860F074[];
|
||
|
extern const u8 *sPokeblocksPals[];
|
||
|
extern const union AffineAnimCmd * const sSpriteAffineAnimTable_85F05B0[];
|
||
|
extern const union AffineAnimCmd * const sSpriteAffineAnimTable_85F0664[];
|
||
|
extern const union AffineAnimCmd * const sSpriteAffineAnimTable_85F0668[];
|
||
|
extern const union AffineAnimCmd * const sSpriteAffineAnimTable_85F066C[];
|
||
|
extern const struct SpriteTemplate sThrownPokeblockSpriteTemplate;
|
||
|
|
||
|
static void HandleInitBackgrounds(void)
|
||
|
{
|
||
|
ResetVramOamAndBgCntRegs();
|
||
|
|
||
|
ResetBgsAndClearDma3BusyFlags(0);
|
||
|
InitBgsFromTemplates(0, gUnknown_085F0550, ARRAY_COUNT(gUnknown_085F0550));
|
||
|
SetBgTilemapBuffer(1, sPokeblockFeed->tilemapBuffer);
|
||
|
ResetAllBgsCoordinates();
|
||
|
schedule_bg_copy_tilemap_to_vram(1);
|
||
|
|
||
|
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
|
||
|
|
||
|
ShowBg(0);
|
||
|
ShowBg(1);
|
||
|
|
||
|
SetGpuReg(REG_OFFSET_BLDCNT, 0);
|
||
|
}
|
||
|
|
||
|
static bool8 LoadMonAndSceneGfx(struct Pokemon *mon)
|
||
|
{
|
||
|
u16 species;
|
||
|
u32 personality, trainerId;
|
||
|
const struct CompressedSpritePalette *palette;
|
||
|
|
||
|
switch (sPokeblockFeed->loadGfxState)
|
||
|
{
|
||
|
case 0:
|
||
|
species = GetMonData(mon, MON_DATA_SPECIES2);
|
||
|
personality = GetMonData(mon, MON_DATA_PERSONALITY);
|
||
|
HandleLoadSpecialPokePic_2(&gMonFrontPicTable[species], gMonSpritesGfxPtr->sprites[1], species, personality);
|
||
|
sPokeblockFeed->loadGfxState++;
|
||
|
break;
|
||
|
case 1:
|
||
|
species = GetMonData(mon, MON_DATA_SPECIES2);
|
||
|
personality = GetMonData(mon, MON_DATA_PERSONALITY);
|
||
|
trainerId = GetMonData(mon, MON_DATA_OT_ID);
|
||
|
palette = GetMonSpritePalStructFromOtIdPersonality(species, trainerId, personality);
|
||
|
|
||
|
LoadCompressedObjectPalette(palette);
|
||
|
sub_806A068(palette->tag, 1);
|
||
|
sPokeblockFeed->loadGfxState++;
|
||
|
break;
|
||
|
case 2:
|
||
|
LoadCompressedObjectPic(&gPokeblockCase_SpriteSheet);
|
||
|
sPokeblockFeed->loadGfxState++;
|
||
|
break;
|
||
|
case 3:
|
||
|
LoadCompressedObjectPalette(&gPokeblockCase_SpritePal);
|
||
|
sPokeblockFeed->loadGfxState++;
|
||
|
break;
|
||
|
case 4:
|
||
|
LoadCompressedObjectPic(&gPokeblock_SpriteSheet);
|
||
|
sPokeblockFeed->loadGfxState++;
|
||
|
break;
|
||
|
case 5:
|
||
|
SetPokeblockSpritePal(gSpecialVar_ItemId);
|
||
|
LoadCompressedObjectPalette(&sPokeblockSpritePal);
|
||
|
sPokeblockFeed->loadGfxState++;
|
||
|
break;
|
||
|
case 6:
|
||
|
reset_temp_tile_data_buffers();
|
||
|
decompress_and_copy_tile_data_to_vram(1, gBattleTerrainTiles_Building, 0, 0, 0);
|
||
|
sPokeblockFeed->loadGfxState++;
|
||
|
break;
|
||
|
case 7:
|
||
|
if (free_temp_tile_data_buffers_if_possible() != TRUE)
|
||
|
{
|
||
|
LZDecompressWram(gUnknown_08D9BA44, sPokeblockFeed->tilemapBuffer);
|
||
|
sPokeblockFeed->loadGfxState++;
|
||
|
}
|
||
|
break;
|
||
|
case 8:
|
||
|
LoadCompressedPalette(gBattleTerrainPalette_Frontier, 0x20, 0x60);
|
||
|
sPokeblockFeed->loadGfxState = 0;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
extern void sub_809882C(u8, u16, u8);
|
||
|
|
||
|
static void HandleInitWindows(void)
|
||
|
{
|
||
|
InitWindows(gUnknown_085F0558);
|
||
|
DeactivateAllTextPrinters();
|
||
|
sub_809882C(0, 1, 0xE0);
|
||
|
LoadPalette(gUnknown_0860F074, 0xF0, 0x20);
|
||
|
FillWindowPixelBuffer(0, 0);
|
||
|
PutWindowTilemap(0);
|
||
|
schedule_bg_copy_tilemap_to_vram(0);
|
||
|
}
|
||
|
|
||
|
static void SetPokeblockSpritePal(u8 pokeblockCaseId)
|
||
|
{
|
||
|
u8 colorId = GetPokeblockData(&gSaveBlock1Ptr->pokeblocks[pokeblockCaseId], PBLOCK_COLOR);
|
||
|
sPokeblockSpritePal.data = sPokeblocksPals[colorId - 1];
|
||
|
sPokeblockSpritePal.tag = TAG_POKEBLOCK_GFX;
|
||
|
}
|
||
|
|
||
|
#define tFrames data[0]
|
||
|
#define tData1 data[1]
|
||
|
|
||
|
void Task_HandlePokeblockFeed(u8 taskId)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
switch (gTasks[taskId].tFrames)
|
||
|
{
|
||
|
case 0:
|
||
|
sPokeblockFeed->field_1050 = 0;
|
||
|
sPokeblockFeed->field_1058 = 0;
|
||
|
sub_817A5CC();
|
||
|
break;
|
||
|
case 255:
|
||
|
DoPokeblockCaseThrowEffect(sPokeblockFeed->pokeblockCaseSpriteId, gTasks[taskId].tData1);
|
||
|
break;
|
||
|
case 269:
|
||
|
sPokeblockFeed->pokeblockSpriteId = CreatePokeblockSprite();
|
||
|
break;
|
||
|
case 281:
|
||
|
PrepareMonToMoveToPokeblock(sPokeblockFeed->monSpriteId);
|
||
|
break;
|
||
|
case 297:
|
||
|
gTasks[taskId].func = Task_HandleMonAtePokeblock;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (sPokeblockFeed->field_1058 < sPokeblockFeed->field_1056)
|
||
|
sub_817A634();
|
||
|
else if (sPokeblockFeed->field_1058 == sPokeblockFeed->field_1056)
|
||
|
gTasks[taskId].tFrames = 254;
|
||
|
|
||
|
sPokeblockFeed->field_1058++;
|
||
|
gTasks[taskId].tFrames++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void LaunchPokeblockFeedTask(void)
|
||
|
{
|
||
|
u8 taskId = CreateTask(Task_HandlePokeblockFeed, 0);
|
||
|
gTasks[taskId].tFrames = 0;
|
||
|
gTasks[taskId].tData1 = 1;
|
||
|
}
|
||
|
|
||
|
void Task_WaitForAtePokeblockText(u8 taskId)
|
||
|
{
|
||
|
if (RunTextPrintersRetIsActive(0) != TRUE)
|
||
|
gTasks[taskId].func = Task_PaletteFadeToReturn;
|
||
|
}
|
||
|
|
||
|
void Task_HandleMonAtePokeblock(u8 taskId)
|
||
|
{
|
||
|
struct Pokemon *mon = &gPlayerParty[gPokeblockMonId];
|
||
|
struct Pokeblock *pokeblock = &gSaveBlock1Ptr->pokeblocks[gSpecialVar_ItemId];
|
||
|
|
||
|
gPokeblockGain = PokeblockGetGain(GetNature(mon), pokeblock);
|
||
|
GetMonNickname(mon, gStringVar1);
|
||
|
PokeblockCopyName(pokeblock, gStringVar2);
|
||
|
|
||
|
if (gPokeblockGain == 0)
|
||
|
StringExpandPlaceholders(gStringVar4, gText_Var1AteTheVar2);
|
||
|
else if (gPokeblockGain > 0)
|
||
|
StringExpandPlaceholders(gStringVar4, gText_Var1HappilyAteVar2);
|
||
|
else
|
||
|
StringExpandPlaceholders(gStringVar4, gText_Var1DisdainfullyAteVar2);
|
||
|
|
||
|
gTextFlags.flag_0 = 1;
|
||
|
AddTextPrinterParametrized(0, 1, gStringVar4, GetPlayerTextSpeed(), NULL, 2, 1, 3);
|
||
|
gTasks[taskId].func = Task_WaitForAtePokeblockText;
|
||
|
}
|
||
|
|
||
|
void Task_ReturnAfterPaletteFade(u8 taskId)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
ResetSpriteData();
|
||
|
FreeAllSpritePalettes();
|
||
|
m4aMPlayVolumeControl(&gMPlay_BGM, -1, 256);
|
||
|
SetMainCallback2(gMain.savedCallback);
|
||
|
DestroyTask(taskId);
|
||
|
FreeAllWindowBuffers();
|
||
|
Free(sPokeblockFeed);
|
||
|
FreeMonSpritesGfx();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Task_PaletteFadeToReturn(u8 taskId)
|
||
|
{
|
||
|
BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
|
||
|
gTasks[taskId].func = Task_ReturnAfterPaletteFade;
|
||
|
}
|
||
|
|
||
|
static u8 CreateMonSprite(struct Pokemon* mon)
|
||
|
{
|
||
|
u16 species = GetMonData(mon, MON_DATA_SPECIES2);
|
||
|
u8 spriteId = CreateSprite(&gUnknown_0202499C, 48, 80, 2);
|
||
|
|
||
|
sPokeblockFeed->species = species;
|
||
|
sPokeblockFeed->monSpriteId_ = spriteId;
|
||
|
sPokeblockFeed->nature = GetNature(mon);
|
||
|
gSprites[spriteId].data2 = species;
|
||
|
gSprites[spriteId].callback = SpriteCallbackDummy;
|
||
|
|
||
|
sPokeblockFeed->noMonFlip = TRUE;
|
||
|
if (!IsPokeSpriteNotFlipped(species))
|
||
|
{
|
||
|
gSprites[spriteId].affineAnims = sSpriteAffineAnimTable_85F05B0;
|
||
|
gSprites[spriteId].oam.affineMode = 3;
|
||
|
CalcCenterToCornerVec(&gSprites[spriteId], gSprites[spriteId].oam.shape, gSprites[spriteId].oam.size, gSprites[spriteId].oam.affineMode);
|
||
|
sPokeblockFeed->noMonFlip = FALSE;
|
||
|
}
|
||
|
|
||
|
return spriteId;
|
||
|
}
|
||
|
|
||
|
static void PrepareMonToMoveToPokeblock(u8 spriteId)
|
||
|
{
|
||
|
gSprites[spriteId].pos1.x = 48;
|
||
|
gSprites[spriteId].pos1.y = 80;
|
||
|
gSprites[spriteId].data0 = -8;
|
||
|
gSprites[spriteId].data1 = 1;
|
||
|
gSprites[spriteId].callback = sub_817A468;
|
||
|
}
|
||
|
|
||
|
static void sub_817A468(struct Sprite* sprite)
|
||
|
{
|
||
|
sprite->pos1.x += 4;
|
||
|
sprite->pos1.y += sprite->data0;
|
||
|
sprite->data0 += sprite->data1;
|
||
|
|
||
|
if (sprite->data0 == 0)
|
||
|
PlayCry1(sprite->data2, 0);
|
||
|
if (sprite->data0 == 9)
|
||
|
sprite->callback = SpriteCallbackDummy;
|
||
|
}
|
||
|
|
||
|
u8 CreatePokeblockCaseSpriteForFeeding(void)
|
||
|
{
|
||
|
u8 spriteId = CreatePokeblockCaseSprite(188, 100, 2);
|
||
|
gSprites[spriteId].oam.affineMode = 1;
|
||
|
gSprites[spriteId].affineAnims = sSpriteAffineAnimTable_85F0664;
|
||
|
gSprites[spriteId].callback = SpriteCallbackDummy;
|
||
|
InitSpriteAffineAnim(&gSprites[spriteId]);
|
||
|
return spriteId;
|
||
|
}
|
||
|
|
||
|
void DoPokeblockCaseThrowEffect(u8 spriteId, bool8 a1)
|
||
|
{
|
||
|
FreeOamMatrix(gSprites[spriteId].oam.matrixNum);
|
||
|
gSprites[spriteId].oam.affineMode = 3;
|
||
|
|
||
|
if (!a1)
|
||
|
gSprites[spriteId].affineAnims = sSpriteAffineAnimTable_85F0668;
|
||
|
else
|
||
|
gSprites[spriteId].affineAnims = sSpriteAffineAnimTable_85F066C;
|
||
|
|
||
|
InitSpriteAffineAnim(&gSprites[spriteId]);
|
||
|
}
|
||
|
|
||
|
u8 CreatePokeblockSprite(void)
|
||
|
{
|
||
|
u8 spriteId = CreateSprite(&sThrownPokeblockSpriteTemplate, 174, 84, 1);
|
||
|
gSprites[spriteId].data0 = -12;
|
||
|
gSprites[spriteId].data1 = 1;
|
||
|
return spriteId;
|
||
|
}
|
||
|
|
||
|
static void SpriteCB_ThrownPokeblock(struct Sprite* sprite)
|
||
|
{
|
||
|
sprite->pos1.x -= 4;
|
||
|
sprite->pos1.y += sprite->data0;
|
||
|
sprite->data0 += sprite->data1;
|
||
|
if (sprite->data0 == 10)
|
||
|
DestroySprite(sprite);
|
||
|
}
|