Files
Pokemon-Firered/src/pokemon_storage_system_2.c
T
2020-03-11 17:03:57 -04:00

653 lines
18 KiB
C

#include "global.h"
#include "gflib.h"
#include "event_data.h"
#include "field_fadetransition.h"
#include "field_weather.h"
#include "help_system.h"
#include "menu.h"
#include "new_menu_helpers.h"
#include "overworld.h"
#include "pokemon_storage_system_internal.h"
#include "script.h"
#include "strings.h"
#include "task.h"
#include "constants/species.h"
#include "constants/songs.h"
#include "constants/field_weather.h"
#include "constants/help_system.h"
struct PSS_MenuStringPtrs
{
const u8 *text;
const u8 *desc;
};
EWRAM_DATA u8 sPreviousBoxOption = 0;
EWRAM_DATA struct UnkPSSStruct_2002370 *gUnknown_20397AC = NULL;
void PSS_CreatePCMenu(u8 whichMenu, s16 *windowIdPtr);
void sub_808C9C4(u8 curBox);
void sub_808CBA4(void);
void sub_808CC10(void);
void sub_808CC44(void);
void sub_808CC74(void);
void sub_808CCFC(const u8 *a0, u16 x, u16 y);
void sub_808CD64(struct Sprite * sprite);
// Forward declarations
const u16 gBoxSelectionPopupPalette[];
const u16 gBoxSelectionPopupCenterTiles[];
const u16 gBoxSelectionPopupSidesTiles[];
const struct PSS_MenuStringPtrs gUnknown_83CDA20[] = {
{gText_WithdrawPokemon, gText_WithdrawMonDescription},
{gText_DepositPokemon, gText_DepositMonDescription },
{gText_MovePokemon, gText_MoveMonDescription },
{gText_MoveItems, gText_MoveItemsDescription },
{gText_SeeYa, gText_SeeYaDescription }
};
void DrawTextWindowAndBufferTiles(const u8 *string, void *dst, u8 zero1, u8 zero2, u8 *buffer, s32 bytesToBuffer)
{
s32 i, tileBytesToBuffer, remainingBytes;
u16 windowId;
u8 txtColor[3];
u8 *tileData1, *tileData2;
struct WindowTemplate winTemplate = {0};
winTemplate.width = 24;
winTemplate.height = 2;
windowId = AddWindow(&winTemplate);
FillWindowPixelBuffer(windowId, PIXEL_FILL(zero2));
tileData1 = (u8*) GetWindowAttribute(windowId, WINDOW_TILE_DATA);
tileData2 = (winTemplate.width * 32) + tileData1;
if (!zero1)
txtColor[0] = TEXT_COLOR_TRANSPARENT;
else
txtColor[0] = zero2;
txtColor[1] = TEXT_DYNAMIC_COLOR_6;
txtColor[2] = TEXT_DYNAMIC_COLOR_5;
AddTextPrinterParameterized4(windowId, 1, 0, 2, 0, 0, txtColor, -1, string);
tileBytesToBuffer = bytesToBuffer;
if (tileBytesToBuffer > 6)
tileBytesToBuffer = 6;
remainingBytes = bytesToBuffer - 6;
if (tileBytesToBuffer > 0)
{
for (i = tileBytesToBuffer; i != 0; i--)
{
CpuCopy16(tileData1, dst, 0x80);
CpuCopy16(tileData2, dst + 0x80, 0x80);
tileData1 += 0x80;
tileData2 += 0x80;
dst += 0x100;
}
}
// Never used. bytesToBuffer is always passed <= 6, so remainingBytes is always <= 0 here
if (remainingBytes > 0)
CpuFill16((zero2 << 4) | zero2, dst, (u32)(remainingBytes) * 0x100);
RemoveWindow(windowId);
}
void sub_808BFE0(const u8 *string, void *dst, u16 arg2, u8 arg3, u8 clr2, u8 clr3, u8 *buffer)
{
u32 var;
u8 windowId;
u8 txtColor[3];
u8 *tileData1, *tileData2;
struct WindowTemplate winTemplate = {0};
winTemplate.width = StringLength_Multibyte(string);
winTemplate.height = 2;
var = winTemplate.width * 32;
windowId = AddWindow(&winTemplate);
FillWindowPixelBuffer(windowId, PIXEL_FILL(arg3));
tileData1 = (u8*) GetWindowAttribute(windowId, WINDOW_TILE_DATA);
tileData2 = (winTemplate.width * 32) + tileData1;
txtColor[0] = arg3;
txtColor[1] = clr2;
txtColor[2] = clr3;
AddTextPrinterParameterized4(windowId, 1, 0, 2, 0, 0, txtColor, -1, string);
CpuCopy16(tileData1, dst, var);
CpuCopy16(tileData2, dst + arg2, var);
RemoveWindow(windowId);
}
u8 CountMonsInBox(u8 boxId)
{
u16 i, count;
for (i = 0, count = 0; i < IN_BOX_COUNT; i++)
{
if (GetBoxMonDataAt(boxId, i, MON_DATA_SPECIES) != SPECIES_NONE)
count++;
}
return count;
}
s16 GetFirstFreeBoxSpot(u8 boxId)
{
u16 i;
for (i = 0; i < IN_BOX_COUNT; i++)
{
if (GetBoxMonDataAt(boxId, i, MON_DATA_SPECIES) == SPECIES_NONE)
return i;
}
return -1; // all spots are taken
}
u8 CountPartyNonEggMons(void)
{
u16 i, count;
for (i = 0, count = 0; i < PARTY_SIZE; i++)
{
if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) != SPECIES_NONE
&& !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))
{
count++;
}
}
return count;
}
u8 CountPartyAliveNonEggMonsExcept(u8 slotToIgnore)
{
u16 i, count;
for (i = 0, count = 0; i < PARTY_SIZE; i++)
{
if (i != slotToIgnore
&& GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) != SPECIES_NONE
&& !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG)
&& GetMonData(&gPlayerParty[i], MON_DATA_HP) != 0)
{
count++;
}
}
return count;
}
u16 CountPartyAliveNonEggMons_IgnoreVar0x8004Slot(void)
{
return CountPartyAliveNonEggMonsExcept(gSpecialVar_0x8004);
}
u8 CountPartyMons(void)
{
u16 i, count;
for (i = 0, count = 0; i < PARTY_SIZE; i++)
{
if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) != SPECIES_NONE)
{
count++;
}
}
return count;
}
u8 *StringCopyAndFillWithSpaces(u8 *dst, const u8 *src, u16 n)
{
u8 *str;
for (str = StringCopy(dst, src); str < dst + n; str++)
*str = CHAR_SPACE;
*str = EOS;
return str;
}
void sub_808C25C(u16 *dest, u16 dest_left, u16 dest_top, const u16 *src, u16 src_left, u16 src_top, u16 dest_width, u16 dest_height, u16 src_width)
{
u16 i;
dest_width *= 2;
dest += dest_top * 0x20 + dest_left;
src += src_top * src_width + src_left;
for (i = 0; i < dest_height; i++)
{
CpuCopy16(src, dest, dest_width);
dest += 0x20;
src += src_width;
}
}
void sub_808C2D8(u16 *dest, u16 dest_left, u16 dest_top, u16 width, u16 height)
{
u16 i;
dest += dest_top * 0x20 + dest_left;
width *= 2;
for (i = 0; i < height; dest += 0x20, i++)
Dma3FillLarge16_(0, dest, width);
}
void Task_PokemonStorageSystemPC(u8 taskId)
{
struct Task *task = &gTasks[taskId];
switch (task->data[0])
{
case 0:
SetHelpContext(HELPCONTEXT_BILLS_PC);
PSS_CreatePCMenu(task->data[1], &task->data[15]);
LoadStdWindowFrameGfx();
DrawDialogueFrame(0, 0);
FillWindowPixelBuffer(0, PIXEL_FILL(1));
AddTextPrinterParameterized2(0, 2, gUnknown_83CDA20[task->data[1]].desc, TEXT_SPEED_FF, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GREY);
CopyWindowToVram(0, 3);
CopyWindowToVram(task->data[15], 3);
task->data[0]++;
break;
case 1:
if (IsWeatherNotFadingIn())
{
task->data[0]++;
}
break;
case 2:
task->data[2] = Menu_ProcessInput();
switch(task->data[2])
{
case MENU_NOTHING_CHOSEN:
task->data[3] = task->data[1];
if (gMain.newKeys & DPAD_UP && --task->data[3] < 0)
task->data[3] = 4;
if (gMain.newKeys & DPAD_DOWN && ++task->data[3] > 4)
task->data[3] = 0;
if (task->data[1] != task->data[3])
{
task->data[1] = task->data[3];
FillWindowPixelBuffer(0, PIXEL_FILL(1));
AddTextPrinterParameterized2(0, 2, gUnknown_83CDA20[task->data[1]].desc, 0, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GREY);
}
break;
case MENU_B_PRESSED:
case 4:
ClearStdWindowAndFrame(0, TRUE);
ClearStdWindowAndFrame(task->data[15], TRUE);
ScriptContext2_Disable();
EnableBothScriptContexts();
DestroyTask(taskId);
break;
default:
if (task->data[2] == 0 && CountPartyMons() == PARTY_SIZE)
{
FillWindowPixelBuffer(0, PIXEL_FILL(1));
AddTextPrinterParameterized2(0, 2, gText_PartyFull, 0, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GREY);
task->data[0] = 3;
}
else if (task->data[2] == 1 && CountPartyMons() == 1)
{
FillWindowPixelBuffer(0, PIXEL_FILL(1));
AddTextPrinterParameterized2(0, 2, gText_JustOnePkmn, 0, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GREY);
task->data[0] = 3;
}
else
{
FadeScreen(FADE_TO_BLACK, 0);
task->data[0] = 4;
}
break;
}
break;
case 3:
if (gMain.newKeys & (A_BUTTON | B_BUTTON))
{
FillWindowPixelBuffer(0, PIXEL_FILL(1));
AddTextPrinterParameterized2(0, 2, gUnknown_83CDA20[task->data[1]].desc, 0, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GREY);
task->data[0] = 2;
}
else if (gMain.newKeys & DPAD_UP)
{
if (--task->data[1] < 0)
task->data[1] = 4;
Menu_MoveCursor(-1);
task->data[1] = Menu_GetCursorPos();
FillWindowPixelBuffer(0, PIXEL_FILL(1));
AddTextPrinterParameterized2(0, 2, gUnknown_83CDA20[task->data[1]].desc, 0, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GREY);
task->data[0] = 2;
}
else if (gMain.newKeys & DPAD_DOWN)
{
if (++task->data[1] > 3)
task->data[1] = 0;
Menu_MoveCursor(1);
task->data[1] = Menu_GetCursorPos();
FillWindowPixelBuffer(0, PIXEL_FILL(1));
AddTextPrinterParameterized2(0, 2, gUnknown_83CDA20[task->data[1]].desc, 0, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GREY);
task->data[0] = 2;
}
break;
case 4:
if (!gPaletteFade.active)
{
CleanupOverworldWindowsAndTilemaps();
Cb2_EnterPSS(task->data[2]);
DestroyTask(taskId);
}
break;
}
}
void ShowPokemonStorageSystemPC(void)
{
u8 taskId = CreateTask(Task_PokemonStorageSystemPC, 80);
gTasks[taskId].data[0] = 0;
gTasks[taskId].data[1] = 0;
ScriptContext2_Enable();
}
void FieldCb_ReturnToPcMenu(void)
{
u8 taskId;
MainCallback vblankCb = gMain.vblankCallback;
SetVBlankCallback(NULL);
taskId = CreateTask(Task_PokemonStorageSystemPC, 80);
gTasks[taskId].data[0] = 0;
gTasks[taskId].data[1] = sPreviousBoxOption;
Task_PokemonStorageSystemPC(taskId);
SetVBlankCallback(vblankCb);
FadeInFromBlack();
}
const struct WindowTemplate gUnknown_83CDA48 = {
.bg = 0,
.tilemapLeft = 1,
.tilemapTop = 1,
.width = 17,
.height = 10,
.paletteNum = 15,
.baseBlock = 0x001
};
void PSS_CreatePCMenu(u8 whichMenu, s16 *windowIdPtr)
{
s16 windowId;
windowId = AddWindow(&gUnknown_83CDA48);
DrawStdWindowFrame(windowId, FALSE);
PrintTextArray(windowId, 2, GetMenuCursorDimensionByFont(2, 0), 2, 16, NELEMS(gUnknown_83CDA20), (void *)gUnknown_83CDA20);
Menu_InitCursor(windowId, 2, 0, 2, 16, NELEMS(gUnknown_83CDA20), whichMenu);
*windowIdPtr = windowId;
}
void Cb2_ExitPSS(void)
{
sPreviousBoxOption = GetCurrentBoxOption();
gFieldCallback = FieldCb_ReturnToPcMenu;
SetMainCallback2(CB2_ReturnToField);
}
void ResetPokemonStorageSystem(void)
{
u16 boxId, boxPosition;
SetCurrentBox(0);
for (boxId = 0; boxId < TOTAL_BOXES_COUNT; boxId++)
{
for (boxPosition = 0; boxPosition < IN_BOX_COUNT; boxPosition++)
ZeroBoxMonAt(boxId, boxPosition);
}
for (boxId = 0; boxId < TOTAL_BOXES_COUNT; boxId++)
{
u8 *dest = StringCopy(GetBoxNamePtr(boxId), gText_Box);
ConvertIntToDecimalStringN(dest, boxId + 1, STR_CONV_MODE_LEFT_ALIGN, 2);
}
for (boxId = 0; boxId < TOTAL_BOXES_COUNT; boxId++)
{
SetBoxWallpaper(boxId, boxId % 4);
}
}
void sub_808C854(struct UnkPSSStruct_2002370 *a0, u16 tileTag, u16 palTag, u8 a3, bool32 loadPal)
{
struct SpritePalette palette = {
gBoxSelectionPopupPalette, palTag
};
struct SpriteSheet sheets[] = {
{gBoxSelectionPopupCenterTiles, 0x800, tileTag},
{gBoxSelectionPopupSidesTiles, 0x180, tileTag + 1},
{}
};
if (loadPal)
LoadSpritePalette(&palette);
LoadSpriteSheets(sheets);
gUnknown_20397AC = a0;
a0->unk_0240 = tileTag;
a0->unk_0242 = palTag;
a0->unk_0246 = a3;
a0->unk_023c = loadPal;
}
void sub_808C8FC(void)
{
if (gUnknown_20397AC->unk_023c)
FreeSpritePaletteByTag(gUnknown_20397AC->unk_0242);
FreeSpriteTilesByTag(gUnknown_20397AC->unk_0240);
FreeSpriteTilesByTag(gUnknown_20397AC->unk_0240 + 1);
}
void sub_808C940(u8 curBox)
{
sub_808C9C4(curBox);
}
void sub_808C950(void)
{
sub_808CBA4();
}
u8 HandleBoxChooseSelectionInput(void)
{
if (gMain.newKeys & B_BUTTON)
{
PlaySE(SE_SELECT);
return 201;
}
if (gMain.newKeys & A_BUTTON)
{
PlaySE(SE_SELECT);
return gUnknown_20397AC->curBox;
}
if (gMain.newKeys & DPAD_LEFT)
{
PlaySE(SE_SELECT);
sub_808CC44();
}
else if (gMain.newKeys & DPAD_RIGHT)
{
PlaySE(SE_SELECT);
sub_808CC10();
}
return 200;
}
const union AnimCmd gUnknown_83CDA50[] = {
ANIMCMD_FRAME( 0, 5),
ANIMCMD_END
};
const union AnimCmd gUnknown_83CDA58[] = {
ANIMCMD_FRAME( 4, 5),
ANIMCMD_END
};
const union AnimCmd gUnknown_83CDA60[] = {
ANIMCMD_FRAME( 6, 5),
ANIMCMD_END
};
const union AnimCmd gUnknown_83CDA68[] = {
ANIMCMD_FRAME(10, 5),
ANIMCMD_END
};
const union AnimCmd *const gUnknown_83CDA70[] = {
gUnknown_83CDA50,
gUnknown_83CDA58,
gUnknown_83CDA60,
gUnknown_83CDA68
};
const union AffineAnimCmd gUnknown_83CDA80[] = {
AFFINEANIMCMD_FRAME(224, 224, 0, 0),
AFFINEANIMCMD_END
};
const union AffineAnimCmd *const gUnknown_83CDA90[] = {
gUnknown_83CDA80
};
void sub_808C9C4(u8 curBox)
{
u16 i;
u8 spriteId;
struct SpriteTemplate template;
struct OamData oamData = {};
oamData.size = SPRITE_SIZE(64x64);
oamData.paletteNum = 1;
template = (struct SpriteTemplate){
0, 0, &oamData, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy
};
{
const u8 gUnknown_83CDA94[] = _("/30");
gUnknown_20397AC->curBox = curBox;
template.tileTag = gUnknown_20397AC->unk_0240;
template.paletteTag = gUnknown_20397AC->unk_0242;
spriteId = CreateSprite(&template, 160, 96, 0);
gUnknown_20397AC->unk_0000 = gSprites + spriteId;
oamData.shape = SPRITE_SHAPE(8x32);
oamData.size = SPRITE_SIZE(8x32);
template.tileTag = gUnknown_20397AC->unk_0240 + 1;
template.anims = gUnknown_83CDA70;
for (i = 0; i < 4; i++)
{
u16 r5;
spriteId = CreateSprite(&template, 124, 80, gUnknown_20397AC->unk_0246);
gUnknown_20397AC->unk_0004[i] = gSprites + spriteId;
r5 = 0;
if (i & 2)
{
gUnknown_20397AC->unk_0004[i]->pos1.x = 196;
r5 = 2;
}
if (i & 1)
{
gUnknown_20397AC->unk_0004[i]->pos1.y = 112;
gUnknown_20397AC->unk_0004[i]->oam.size = 0;
r5++;
}
StartSpriteAnim(gUnknown_20397AC->unk_0004[i], r5);
}
for (i = 0; i < 2; i++)
{
gUnknown_20397AC->unk_0020[i] = sub_809223C(72 * i + 0x7c, 0x58, i, 0, gUnknown_20397AC->unk_0246);
if (gUnknown_20397AC->unk_0020[i])
{
gUnknown_20397AC->unk_0020[i]->data[0] = (i == 0 ? -1 : 1);
gUnknown_20397AC->unk_0020[i]->callback = sub_808CD64;
}
}
sub_808CC74();
sub_808CCFC(gUnknown_83CDA94, 5, 3);
}
}
void sub_808CBA4(void)
{
u16 i;
if (gUnknown_20397AC->unk_0000)
{
DestroySprite(gUnknown_20397AC->unk_0000);
gUnknown_20397AC->unk_0000 = NULL;
}
for (i = 0; i < 4; i++)
{
if (gUnknown_20397AC->unk_0004[i])
{
DestroySprite(gUnknown_20397AC->unk_0004[i]);
gUnknown_20397AC->unk_0004[i] = NULL;
}
}
for (i = 0; i < 2; i++)
{
if (gUnknown_20397AC->unk_0020[i])
DestroySprite(gUnknown_20397AC->unk_0020[i]);
}
}
void sub_808CC10(void)
{
if (++gUnknown_20397AC->curBox >= TOTAL_BOXES_COUNT)
gUnknown_20397AC->curBox = 0;
sub_808CC74();
}
void sub_808CC44(void)
{
gUnknown_20397AC->curBox = (gUnknown_20397AC->curBox == 0 ? TOTAL_BOXES_COUNT - 1 : gUnknown_20397AC->curBox - 1);
sub_808CC74();
}
void sub_808CC74(void)
{
u8 nPokemonInBox = CountMonsInBox(gUnknown_20397AC->curBox);
u8 *boxName = StringCopy(gUnknown_20397AC->unk_0228, GetBoxNamePtr(gUnknown_20397AC->curBox));
while (boxName < gUnknown_20397AC->unk_0228 + BOX_NAME_LENGTH)
*boxName++ = CHAR_SPACE;
*boxName = EOS;
sub_808CCFC(gUnknown_20397AC->unk_0228, 0, 1);
ConvertIntToDecimalStringN(gUnknown_20397AC->unk_0228, nPokemonInBox, STR_CONV_MODE_RIGHT_ALIGN, 2);
sub_808CCFC(gUnknown_20397AC->unk_0228, 3, 3);
}
void sub_808CCFC(const u8 *str, u16 x, u16 y)
{
u16 tileStart = GetSpriteTileStartByTag(gUnknown_20397AC->unk_0240);
sub_808BFE0(str, (void *)(OBJ_VRAM0 + tileStart * 32 + 256 * y + 32 * x), 0x100, 4, 15, 14, gUnknown_20397AC->filler_0028);
}
void sub_808CD64(struct Sprite *sprite)
{
if (++sprite->data[1] > 3)
{
sprite->data[1] = 0;
sprite->pos2.x += sprite->data[0];
if (++sprite->data[2] > 5)
{
sprite->data[2] = 0;
sprite->pos2.x = 0;
}
}
}
// Forward-declared rodata
const u16 gBoxSelectionPopupPalette[] = INCBIN_U16("graphics/interface/pss_unk_83CDA98.gbapal");
const u16 gBoxSelectionPopupCenterTiles[] = INCBIN_U16("graphics/interface/pss_unk_83CDAB8.4bpp");
const u16 gBoxSelectionPopupSidesTiles[] = INCBIN_U16("graphics/interface/pss_unk_83CE2B8.4bpp");