mirror of
https://github.com/pret/pokefirered.git
synced 2026-05-09 21:25:42 -05:00
1728 lines
55 KiB
C
1728 lines
55 KiB
C
#include "global.h"
|
|
#include "tm_case.h"
|
|
#include "gflib.h"
|
|
#include "decompress.h"
|
|
#include "graphics.h"
|
|
#include "task.h"
|
|
#include "text_window.h"
|
|
#include "menu.h"
|
|
#include "menu_helpers.h"
|
|
#include "list_menu.h"
|
|
#include "item.h"
|
|
#include "item_menu.h"
|
|
#include "link.h"
|
|
#include "money.h"
|
|
#include "shop.h"
|
|
#include "teachy_tv.h"
|
|
#include "move.h"
|
|
#include "pokemon_storage_system.h"
|
|
#include "party_menu.h"
|
|
#include "data.h"
|
|
#include "scanline_effect.h"
|
|
#include "strings.h"
|
|
#include "menu_indicators.h"
|
|
#include "constants/items.h"
|
|
#include "constants/songs.h"
|
|
#include "constants/quest_log.h"
|
|
|
|
#define TAG_SCROLL_ARROW 110
|
|
|
|
enum {
|
|
WIN_LIST,
|
|
WIN_DESCRIPTION,
|
|
WIN_SELECTED_MSG,
|
|
WIN_TITLE,
|
|
WIN_MOVE_INFO_LABELS,
|
|
WIN_MOVE_INFO,
|
|
WIN_MESSAGE,
|
|
WIN_SELL_QUANTITY,
|
|
WIN_MONEY,
|
|
};
|
|
|
|
// Window IDs for the context menu that opens when a TM/HM is selected
|
|
enum {
|
|
WIN_USE_GIVE_EXIT,
|
|
WIN_GIVE_EXIT,
|
|
};
|
|
|
|
// IDs for the actions in the context menu
|
|
enum {
|
|
ACTION_USE,
|
|
ACTION_GIVE,
|
|
ACTION_EXIT
|
|
};
|
|
|
|
enum {
|
|
COLOR_LIGHT,
|
|
COLOR_DARK,
|
|
COLOR_CURSOR_SELECTED,
|
|
COLOR_MOVE_INFO,
|
|
COLOR_CURSOR_ERASE = 0xFF
|
|
};
|
|
|
|
// Base position for TM/HM disc sprite
|
|
#define DISC_BASE_X 41
|
|
#define DISC_BASE_Y 46
|
|
|
|
#define DISC_CASE_DISTANCE 20 // The total number of pixels a disc travels vertically in/out of the case
|
|
#define DISC_Y_MOVE 10 // The number of pixels a disc travels vertically per movement step
|
|
|
|
#define TAG_DISC 400
|
|
|
|
#define DISC_HIDDEN 0xFF // When no TM/HM is selected, hide the disc sprite
|
|
|
|
enum {
|
|
ANIM_TM,
|
|
ANIM_HM,
|
|
};
|
|
|
|
// The "static" resources are preserved even if the TM case is exited. This is
|
|
// useful for when its left temporarily (e.g. going to the party menu to teach a TM)
|
|
// but also to preserve the selected item when the TM case is fully closed.
|
|
static EWRAM_DATA struct {
|
|
void (* exitCallback)(void);
|
|
u8 menuType;
|
|
bool8 allowSelectClose;
|
|
u8 unused;
|
|
u16 selectedRow;
|
|
u16 scrollOffset;
|
|
} sTMCaseStaticResources = {};
|
|
|
|
// The "dynamic" resources will be reset any time the TM case is exited, even temporarily.
|
|
static EWRAM_DATA struct {
|
|
void (* nextScreenCallback)(void);
|
|
u8 discSpriteId;
|
|
u8 maxTMsShown;
|
|
u8 numTMs;
|
|
u8 contextMenuWindowId;
|
|
u8 scrollArrowsTaskId;
|
|
u16 currItem;
|
|
const u8 * menuActionIndices;
|
|
u8 numMenuActions;
|
|
s16 seqId;
|
|
u8 unused[8];
|
|
} * sTMCaseDynamicResources = NULL;
|
|
|
|
// Save the player's bag state when the Pokedude's bag is being shown
|
|
static EWRAM_DATA struct {
|
|
struct ItemSlot bagPocket_TMHM[BAG_TMHM_COUNT];
|
|
struct ItemSlot bagPocket_KeyItems[BAG_KEYITEMS_COUNT];
|
|
u16 selectedRow;
|
|
u16 scrollOffset;
|
|
} * sPokedudeBagBackup = NULL;
|
|
|
|
static EWRAM_DATA void *sTilemapBuffer = NULL;
|
|
static EWRAM_DATA struct ListMenuItem * sListMenuItemsBuffer = NULL;
|
|
static EWRAM_DATA u8 (* sListMenuStringsBuffer)[29] = NULL;
|
|
|
|
static void CB2_SetUpTMCaseUI_Blocking(void);
|
|
static bool8 DoSetUpTMCaseUI(void);
|
|
static void ResetBufferPointers_NoFree(void);
|
|
static void LoadBGTemplates(void);
|
|
static bool8 HandleLoadTMCaseGraphicsAndPalettes(void);
|
|
static void CreateTMCaseListMenuBuffers(void);
|
|
static void InitTMCaseListMenuItems(void);
|
|
static void GetTMNumberAndMoveString(u8 * dest, u16 itemId);
|
|
static void List_MoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMenu *list);
|
|
static void List_ItemPrintFunc(u8 windowId, u32 itemId, u8 y);
|
|
static void PrintDescription(s32 itemIndex);
|
|
static void PrintMoveInfo(u16 itemId);
|
|
static void PrintListCursorAtRow(u8 y, u8 colorIdx);
|
|
static void CreateListScrollArrows(void);
|
|
static void TMCaseSetup_GetTMCount(void);
|
|
static void TMCaseSetup_InitListMenuPositions(void);
|
|
static void TMCaseSetup_UpdateVisualMenuOffset(void);
|
|
static void Task_FadeOutAndCloseTMCase(u8 taskId);
|
|
static void Task_HandleListInput(u8 taskId);
|
|
static void Task_SelectedTMHM_Field(u8 taskId);
|
|
static void Task_ContextMenu_HandleInput(u8 taskId);
|
|
static void Action_Use(u8 taskId);
|
|
static void Action_Give(u8 taskId);
|
|
static void PrintError_ThereIsNoPokemon(u8 taskId);
|
|
static void PrintError_ItemCantBeHeld(u8 taskId);
|
|
static void Task_WaitButtonAfterErrorPrint(u8 taskId);
|
|
static void CloseMessageAndReturnToList(u8 taskId);
|
|
static void Action_Exit(u8 taskId);
|
|
static void Task_SelectedTMHM_GiveParty(u8 taskId);
|
|
static void Task_SelectedTMHM_GivePC(u8 taskId);
|
|
static void Task_SelectedTMHM_Sell(u8 taskId);
|
|
static void Task_AskConfirmSaleWithAmount(u8 taskId);
|
|
static void Task_PlaceYesNoBox(u8 taskId);
|
|
static void Task_SaleOfTMsCanceled(u8 taskId);
|
|
static void Task_InitQuantitySelectUI(u8 taskId);
|
|
static void SellTM_PrintQuantityAndSalePrice(s16 quantity, s32 value);
|
|
static void Task_QuantitySelect_HandleInput(u8 taskId);
|
|
static void Task_PrintSaleConfirmedText(u8 taskId);
|
|
static void Task_DoSaleOfTMs(u8 taskId);
|
|
static void Task_AfterSale_ReturnToList(u8 taskId);
|
|
static void Task_Pokedude_Start(u8 taskId);
|
|
static void Task_Pokedude_Run(u8 taskId);
|
|
static void InitWindowTemplatesAndPals(void);
|
|
static void TMCase_Print(u8 windowId, u8 fontId, const u8 * str, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, u8 speed, u8 colorIdx);
|
|
static void TMCase_SetWindowBorder1(u8 windowId);
|
|
static void TMCase_SetWindowBorder2(u8 windowId);
|
|
static void PrintMessageWithFollowupTask(u8 taskId, u8 fontId, const u8 * str, TaskFunc func);
|
|
static void PrintTitle(void);
|
|
static void DrawMoveInfoLabels(void);
|
|
static void PlaceHMTileInWindow(u8 windowId, u8 x, u8 y);
|
|
static void PrintPlayersMoney(void);
|
|
static void HandleCreateYesNoMenu(u8 taskId, const struct YesNoFuncTable * ptrs);
|
|
static u8 AddContextMenu(u8 * windowId, u8 windowIndex);
|
|
static void RemoveContextMenu(u8 * windowId);
|
|
static u8 CreateDiscSprite(u16 itemId);
|
|
static void SetDiscSpriteAnim(struct Sprite *sprite, u8 tmIdx);
|
|
static void TintDiscpriteByType(u8 type);
|
|
static void SetDiscSpritePosition(struct Sprite *sprite, u8 tmIdx);
|
|
static void SwapDisc(u8 spriteId, u16 itemId);
|
|
static void SpriteCB_SwapDisc(struct Sprite *sprite);
|
|
|
|
static const struct BgTemplate sBGTemplates[] = {
|
|
{
|
|
.bg = 0,
|
|
.charBaseIndex = 0,
|
|
.mapBaseIndex = 31,
|
|
.screenSize = 0,
|
|
.paletteMode = 0,
|
|
.priority = 1,
|
|
.baseTile = 0x000
|
|
}, {
|
|
.bg = 1,
|
|
.charBaseIndex = 0,
|
|
.mapBaseIndex = 30,
|
|
.screenSize = 0,
|
|
.paletteMode = 0,
|
|
.priority = 0,
|
|
.baseTile = 0x000
|
|
}, {
|
|
.bg = 2,
|
|
.charBaseIndex = 0,
|
|
.mapBaseIndex = 29,
|
|
.screenSize = 0,
|
|
.paletteMode = 0,
|
|
.priority = 2,
|
|
.baseTile = 0x000
|
|
}
|
|
};
|
|
|
|
// The list of functions to run when a TM/HM is selected.
|
|
// What happens when one is selected depends on how the player arrived at the TM case
|
|
static void (*const sSelectTMActionTasks[])(u8 taskId) = {
|
|
[TMCASE_FIELD] = Task_SelectedTMHM_Field,
|
|
[TMCASE_GIVE_PARTY] = Task_SelectedTMHM_GiveParty,
|
|
[TMCASE_SELL] = Task_SelectedTMHM_Sell,
|
|
[TMCASE_GIVE_PC] = Task_SelectedTMHM_GivePC
|
|
};
|
|
|
|
static const struct MenuAction sMenuActions[] = {
|
|
[ACTION_USE] = {gOtherText_Use, {Action_Use} },
|
|
[ACTION_GIVE] = {gOtherText_Give, {Action_Give} },
|
|
[ACTION_EXIT] = {gOtherText_Exit, {Action_Exit} },
|
|
};
|
|
|
|
static const u8 sMenuActionIndices_Field[] = {ACTION_USE, ACTION_GIVE, ACTION_EXIT};
|
|
static const u8 sMenuActionIndices_UnionRoom[] = {ACTION_GIVE, ACTION_EXIT};
|
|
|
|
static const struct YesNoFuncTable sYesNoFuncTable = {Task_PrintSaleConfirmedText, Task_SaleOfTMsCanceled};
|
|
|
|
static const u8 sText_ClearTo18[] = _("{CLEAR_TO 18}");
|
|
static const u8 sText_SingleSpace[] = _(" ");
|
|
|
|
static ALIGNED(4) const u16 sPal3Override[] = {RGB(8, 8, 8), RGB(30, 16, 6)};
|
|
|
|
static const u8 sTextColors[][3] = {
|
|
[COLOR_LIGHT] = {0, 1, 2},
|
|
[COLOR_DARK] = {0, 2, 3},
|
|
[COLOR_CURSOR_SELECTED] = {0, 3, 6},
|
|
[COLOR_MOVE_INFO] = {0, 14, 10},
|
|
};
|
|
|
|
static const struct WindowTemplate sWindowTemplates[] = {
|
|
[WIN_LIST] = {
|
|
.bg = 0,
|
|
.tilemapLeft = 10,
|
|
.tilemapTop = 1,
|
|
.width = 19,
|
|
.height = 10,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x081
|
|
},
|
|
[WIN_DESCRIPTION] = {
|
|
.bg = 0,
|
|
.tilemapLeft = 12,
|
|
.tilemapTop = 12,
|
|
.width = 18,
|
|
.height = 8,
|
|
.paletteNum = 10,
|
|
.baseBlock = 0x13f
|
|
},
|
|
[WIN_SELECTED_MSG] = {
|
|
.bg = 1,
|
|
.tilemapLeft = 5,
|
|
.tilemapTop = 15,
|
|
.width = 15,
|
|
.height = 4,
|
|
.paletteNum = 13,
|
|
.baseBlock = 0x1f9
|
|
},
|
|
[WIN_TITLE] = {
|
|
.bg = 0,
|
|
.tilemapLeft = 0,
|
|
.tilemapTop = 1,
|
|
.width = 10,
|
|
.height = 2,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x235
|
|
},
|
|
[WIN_MOVE_INFO_LABELS] = {
|
|
.bg = 0,
|
|
.tilemapLeft = 1,
|
|
.tilemapTop = 13,
|
|
.width = 5,
|
|
.height = 6,
|
|
.paletteNum = 12,
|
|
.baseBlock = 0x249
|
|
},
|
|
[WIN_MOVE_INFO] = {
|
|
.bg = 0,
|
|
.tilemapLeft = 7,
|
|
.tilemapTop = 13,
|
|
.width = 5,
|
|
.height = 6,
|
|
.paletteNum = 12,
|
|
.baseBlock = 0x267
|
|
},
|
|
[WIN_MESSAGE] = {
|
|
.bg = 1,
|
|
.tilemapLeft = 2,
|
|
.tilemapTop = 15,
|
|
.width = 26,
|
|
.height = 4,
|
|
.paletteNum = 11,
|
|
.baseBlock = 0x285
|
|
},
|
|
[WIN_SELL_QUANTITY] = {
|
|
.bg = 1,
|
|
.tilemapLeft = 17,
|
|
.tilemapTop = 9,
|
|
.width = 12,
|
|
.height = 4,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x2ed
|
|
},
|
|
[WIN_MONEY] = {
|
|
.bg = 1,
|
|
.tilemapLeft = 1,
|
|
.tilemapTop = 1,
|
|
.width = 8,
|
|
.height = 3,
|
|
.paletteNum = 13,
|
|
.baseBlock = 0x31d
|
|
},
|
|
DUMMY_WIN_TEMPLATE
|
|
};
|
|
|
|
static const struct WindowTemplate sYesNoWindowTemplate = {
|
|
.bg = 1,
|
|
.tilemapLeft = 21,
|
|
.tilemapTop = 9,
|
|
.width = 6,
|
|
.height = 4,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x335
|
|
};
|
|
|
|
static const struct WindowTemplate sWindowTemplates_ContextMenu[] = {
|
|
[WIN_USE_GIVE_EXIT] = {
|
|
.bg = 1,
|
|
.tilemapLeft = 22,
|
|
.tilemapTop = 13,
|
|
.width = 7,
|
|
.height = 6,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x1cf
|
|
},
|
|
[WIN_GIVE_EXIT] = {
|
|
.bg = 1,
|
|
.tilemapLeft = 22,
|
|
.tilemapTop = 15,
|
|
.width = 7,
|
|
.height = 4,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x1cf
|
|
},
|
|
};
|
|
|
|
static const struct OamData sTMSpriteOamData = {
|
|
.size = 2,
|
|
.priority = 2
|
|
};
|
|
|
|
static const union AnimCmd sAnim_TM[] = {
|
|
ANIMCMD_FRAME(0, 0),
|
|
ANIMCMD_END
|
|
};
|
|
|
|
static const union AnimCmd sAnim_HM[] = {
|
|
ANIMCMD_FRAME(16, 0),
|
|
ANIMCMD_END
|
|
};
|
|
|
|
static const union AnimCmd *const sAnims_Disc[] = {
|
|
[ANIM_TM] = sAnim_TM,
|
|
[ANIM_HM] = sAnim_HM
|
|
};
|
|
|
|
static const struct CompressedSpriteSheet sSpriteSheet_Disc = {
|
|
.data = gTMCaseDisc_Gfx,
|
|
.size = 0x400,
|
|
.tag = TAG_DISC
|
|
};
|
|
|
|
static const struct SpriteTemplate sSpriteTemplate_Disc = {
|
|
.tileTag = TAG_DISC,
|
|
.paletteTag = TAG_DISC,
|
|
.oam = &sTMSpriteOamData,
|
|
.anims = sAnims_Disc,
|
|
.images = NULL,
|
|
.affineAnims = gDummySpriteAffineAnimTable,
|
|
.callback = SpriteCallbackDummy
|
|
};
|
|
|
|
static const u16 sTMSpritePaletteOffsetByType[NUMBER_OF_MON_TYPES] = {
|
|
[TYPE_NORMAL] = 0x000,
|
|
[TYPE_FIRE] = 0x010,
|
|
[TYPE_WATER] = 0x020,
|
|
[TYPE_GRASS] = 0x030,
|
|
[TYPE_ELECTRIC] = 0x040,
|
|
[TYPE_ROCK] = 0x050,
|
|
[TYPE_GROUND] = 0x060,
|
|
[TYPE_ICE] = 0x070,
|
|
[TYPE_FLYING] = 0x080,
|
|
[TYPE_FIGHTING] = 0x090,
|
|
[TYPE_GHOST] = 0x0a0,
|
|
[TYPE_BUG] = 0x0b0,
|
|
[TYPE_POISON] = 0x0c0,
|
|
[TYPE_PSYCHIC] = 0x0d0,
|
|
[TYPE_STEEL] = 0x0e0,
|
|
[TYPE_DARK] = 0x0f0,
|
|
[TYPE_DRAGON] = 0x100,
|
|
[TYPE_FAIRY] = 0x0f0,
|
|
};
|
|
|
|
void InitTMCase(u8 type, void (* exitCallback)(void), bool8 allowSelectClose)
|
|
{
|
|
ResetBufferPointers_NoFree();
|
|
sTMCaseDynamicResources = Alloc(sizeof(*sTMCaseDynamicResources));
|
|
sTMCaseDynamicResources->nextScreenCallback = NULL;
|
|
sTMCaseDynamicResources->scrollArrowsTaskId = TASK_NONE;
|
|
sTMCaseDynamicResources->contextMenuWindowId = WINDOW_NONE;
|
|
if (type != TMCASE_REOPENING)
|
|
sTMCaseStaticResources.menuType = type;
|
|
if (exitCallback != NULL)
|
|
sTMCaseStaticResources.exitCallback = exitCallback;
|
|
if (allowSelectClose != TMCASE_KEEP_PREV)
|
|
sTMCaseStaticResources.allowSelectClose = allowSelectClose;
|
|
gTextFlags.autoScroll = FALSE;
|
|
SetMainCallback2(CB2_SetUpTMCaseUI_Blocking);
|
|
}
|
|
|
|
static void CB2_Idle(void)
|
|
{
|
|
RunTasks();
|
|
AnimateSprites();
|
|
BuildOamBuffer();
|
|
DoScheduledBgTilemapCopiesToVram();
|
|
UpdatePaletteFade();
|
|
}
|
|
|
|
static void VBlankCB_Idle(void)
|
|
{
|
|
LoadOam();
|
|
ProcessSpriteCopyRequests();
|
|
TransferPlttBuffer();
|
|
}
|
|
|
|
static void CB2_SetUpTMCaseUI_Blocking(void)
|
|
{
|
|
while (1)
|
|
{
|
|
if (IsActiveOverworldLinkBusy() == TRUE)
|
|
break;
|
|
if (DoSetUpTMCaseUI() == TRUE)
|
|
break;
|
|
if (MenuHelpers_IsLinkActive() == TRUE)
|
|
break;
|
|
}
|
|
}
|
|
|
|
#define tListTaskId data[0]
|
|
#define tSelection data[1]
|
|
#define tQuantityOwned data[2]
|
|
#define tQuantitySelected data[8]
|
|
|
|
#define tPokedudeState data[8] // Re-used
|
|
#define tPokedudeTimer data[9]
|
|
|
|
static bool8 DoSetUpTMCaseUI(void)
|
|
{
|
|
u8 taskId;
|
|
|
|
switch (gMain.state)
|
|
{
|
|
case 0:
|
|
SetVBlankHBlankCallbacksToNull();
|
|
ClearScheduledBgCopiesToVram();
|
|
gMain.state++;
|
|
break;
|
|
case 1:
|
|
ScanlineEffect_Stop();
|
|
gMain.state++;
|
|
break;
|
|
case 2:
|
|
FreeAllSpritePalettes();
|
|
gMain.state++;
|
|
break;
|
|
case 3:
|
|
ResetPaletteFade();
|
|
gMain.state++;
|
|
break;
|
|
case 4:
|
|
ResetSpriteData();
|
|
gMain.state++;
|
|
break;
|
|
case 5:
|
|
ResetTasks();
|
|
gMain.state++;
|
|
break;
|
|
case 6:
|
|
LoadBGTemplates();
|
|
sTMCaseDynamicResources->seqId = 0;
|
|
gMain.state++;
|
|
break;
|
|
case 7:
|
|
InitWindowTemplatesAndPals();
|
|
gMain.state++;
|
|
break;
|
|
case 8:
|
|
if (HandleLoadTMCaseGraphicsAndPalettes())
|
|
gMain.state++;
|
|
break;
|
|
case 9:
|
|
SortPocketAndPlaceHMsFirst(&gBagPockets[POCKET_TM_HM - 1]);
|
|
gMain.state++;
|
|
break;
|
|
case 10:
|
|
TMCaseSetup_GetTMCount();
|
|
TMCaseSetup_InitListMenuPositions();
|
|
TMCaseSetup_UpdateVisualMenuOffset();
|
|
gMain.state++;
|
|
break;
|
|
case 11:
|
|
DrawMoveInfoLabels();
|
|
gMain.state++;
|
|
break;
|
|
case 12:
|
|
CreateTMCaseListMenuBuffers();
|
|
InitTMCaseListMenuItems();
|
|
gMain.state++;
|
|
break;
|
|
case 13:
|
|
PrintTitle();
|
|
gMain.state++;
|
|
break;
|
|
case 14:
|
|
if (sTMCaseStaticResources.menuType == TMCASE_POKEDUDE)
|
|
taskId = CreateTask(Task_Pokedude_Start, 0);
|
|
else
|
|
taskId = CreateTask(Task_HandleListInput, 0);
|
|
gTasks[taskId].tListTaskId = ListMenuInit(&gMultiuseListMenuTemplate, sTMCaseStaticResources.scrollOffset, sTMCaseStaticResources.selectedRow);
|
|
gMain.state++;
|
|
break;
|
|
case 15:
|
|
CreateListScrollArrows();
|
|
gMain.state++;
|
|
break;
|
|
case 16:
|
|
sTMCaseDynamicResources->discSpriteId = CreateDiscSprite(BagGetItemIdByPocketPosition(POCKET_TM_HM, sTMCaseStaticResources.scrollOffset + sTMCaseStaticResources.selectedRow));
|
|
gMain.state++;
|
|
break;
|
|
case 17:
|
|
BlendPalettes(PALETTES_ALL, 16, 0);
|
|
gMain.state++;
|
|
break;
|
|
case 18:
|
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
|
|
gMain.state++;
|
|
break;
|
|
default:
|
|
SetVBlankCallback(VBlankCB_Idle);
|
|
SetMainCallback2(CB2_Idle);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void ResetBufferPointers_NoFree(void)
|
|
{
|
|
sTMCaseDynamicResources = NULL;
|
|
sTilemapBuffer = NULL;
|
|
sListMenuItemsBuffer = NULL;
|
|
sListMenuStringsBuffer = NULL;
|
|
}
|
|
|
|
static void LoadBGTemplates(void)
|
|
{
|
|
void ** ptr;
|
|
ResetAllBgsCoordinatesAndBgCntRegs();
|
|
ptr = &sTilemapBuffer;
|
|
*ptr = AllocZeroed(0x800);
|
|
ResetBgsAndClearDma3BusyFlags(0);
|
|
InitBgsFromTemplates(0, sBGTemplates, ARRAY_COUNT(sBGTemplates));
|
|
SetBgTilemapBuffer(2, *ptr);
|
|
ScheduleBgCopyTilemapToVram(1);
|
|
ScheduleBgCopyTilemapToVram(2);
|
|
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
|
|
SetGpuReg(REG_OFFSET_BLDCNT, 0);
|
|
ShowBg(0);
|
|
ShowBg(1);
|
|
ShowBg(2);
|
|
}
|
|
|
|
static bool8 HandleLoadTMCaseGraphicsAndPalettes(void)
|
|
{
|
|
switch (sTMCaseDynamicResources->seqId)
|
|
{
|
|
case 0:
|
|
ResetTempTileDataBuffers();
|
|
DecompressAndCopyTileDataToVram(1, gTMCase_Gfx, 0, 0, 0);
|
|
sTMCaseDynamicResources->seqId++;
|
|
break;
|
|
case 1:
|
|
if (FreeTempTileDataBuffersIfPossible() != TRUE)
|
|
{
|
|
DecompressDataWithHeaderWram(gTMCaseMenu_Tilemap, sTilemapBuffer);
|
|
sTMCaseDynamicResources->seqId++;
|
|
}
|
|
break;
|
|
case 2:
|
|
DecompressDataWithHeaderWram(gTMCase_Tilemap, GetBgTilemapBuffer(1));
|
|
sTMCaseDynamicResources->seqId++;
|
|
break;
|
|
case 3:
|
|
if (gSaveBlock2Ptr->playerGender == MALE)
|
|
LoadPalette(gTMCaseMenu_Male_Pal, BG_PLTT_ID(0), 4 * PLTT_SIZE_4BPP);
|
|
else
|
|
LoadPalette(gTMCaseMenu_Female_Pal, BG_PLTT_ID(0), 4 * PLTT_SIZE_4BPP);
|
|
sTMCaseDynamicResources->seqId++;
|
|
break;
|
|
case 4:
|
|
LoadCompressedSpriteSheet(&sSpriteSheet_Disc);
|
|
sTMCaseDynamicResources->seqId++;
|
|
break;
|
|
default:
|
|
sTMCaseDynamicResources->seqId = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void CreateTMCaseListMenuBuffers(void)
|
|
{
|
|
struct BagPocket * pocket = &gBagPockets[POCKET_TM_HM - 1];
|
|
sListMenuItemsBuffer = Alloc((pocket->capacity + 1) * sizeof(struct ListMenuItem));
|
|
sListMenuStringsBuffer = Alloc(sTMCaseDynamicResources->numTMs * 29);
|
|
}
|
|
|
|
static void InitTMCaseListMenuItems(void)
|
|
{
|
|
struct BagPocket * pocket = &gBagPockets[POCKET_TM_HM - 1];
|
|
u16 i;
|
|
|
|
for (i = 0; i < sTMCaseDynamicResources->numTMs; i++)
|
|
{
|
|
GetTMNumberAndMoveString(sListMenuStringsBuffer[i], pocket->itemSlots[i].itemId);
|
|
sListMenuItemsBuffer[i].label = sListMenuStringsBuffer[i];
|
|
sListMenuItemsBuffer[i].index = i;
|
|
}
|
|
sListMenuItemsBuffer[i].label = gText_Close;
|
|
sListMenuItemsBuffer[i].index = LIST_CANCEL;
|
|
|
|
gMultiuseListMenuTemplate.items = sListMenuItemsBuffer;
|
|
gMultiuseListMenuTemplate.totalItems = sTMCaseDynamicResources->numTMs + 1; // +1 for Cancel
|
|
gMultiuseListMenuTemplate.windowId = WIN_LIST;
|
|
gMultiuseListMenuTemplate.header_X = 0;
|
|
gMultiuseListMenuTemplate.item_X = 8;
|
|
gMultiuseListMenuTemplate.cursor_X = 0;
|
|
gMultiuseListMenuTemplate.lettersSpacing = 0;
|
|
gMultiuseListMenuTemplate.itemVerticalPadding = 2;
|
|
gMultiuseListMenuTemplate.upText_Y = 2;
|
|
gMultiuseListMenuTemplate.maxShowed = sTMCaseDynamicResources->maxTMsShown;
|
|
gMultiuseListMenuTemplate.fontId = FONT_NORMAL;
|
|
gMultiuseListMenuTemplate.cursorPal = 2;
|
|
gMultiuseListMenuTemplate.fillValue = 0;
|
|
gMultiuseListMenuTemplate.cursorShadowPal = 3;
|
|
gMultiuseListMenuTemplate.moveCursorFunc = List_MoveCursorFunc;
|
|
gMultiuseListMenuTemplate.itemPrintFunc = List_ItemPrintFunc;
|
|
gMultiuseListMenuTemplate.cursorKind = 0;
|
|
gMultiuseListMenuTemplate.scrollMultiple = 0;
|
|
}
|
|
|
|
static void GetTMNumberAndMoveString(u8 * dest, u16 itemId)
|
|
{
|
|
StringCopy(gStringVar4, gText_FontSmall);
|
|
if (IsItemHM(itemId))
|
|
{
|
|
StringAppend(gStringVar4, sText_ClearTo18);
|
|
StringAppend(gStringVar4, gText_NumberClear01);
|
|
ConvertIntToDecimalStringN(gStringVar1, itemId - ITEM_HM01 + 1, STR_CONV_MODE_LEADING_ZEROS, 1);
|
|
StringAppend(gStringVar4, gStringVar1);
|
|
}
|
|
else
|
|
{
|
|
StringAppend(gStringVar4, gText_NumberClear01);
|
|
ConvertIntToDecimalStringN(gStringVar1, itemId - ITEM_TM01 + 1, STR_CONV_MODE_LEADING_ZEROS, 2);
|
|
StringAppend(gStringVar4, gStringVar1);
|
|
}
|
|
StringAppend(gStringVar4, sText_SingleSpace);
|
|
StringAppend(gStringVar4, gText_FontNormal);
|
|
StringAppend(gStringVar4, gMovesInfo[ItemIdToBattleMoveId(itemId)].name);
|
|
StringCopy(dest, gStringVar4);
|
|
}
|
|
|
|
static void List_MoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMenu *list)
|
|
{
|
|
u16 itemId;
|
|
|
|
if (itemIndex == LIST_CANCEL)
|
|
itemId = ITEM_NONE;
|
|
else
|
|
itemId = BagGetItemIdByPocketPosition(POCKET_TM_HM, itemIndex);
|
|
|
|
if (onInit != TRUE)
|
|
{
|
|
PlaySE(SE_SELECT);
|
|
SwapDisc(sTMCaseDynamicResources->discSpriteId, itemId);
|
|
}
|
|
PrintDescription(itemIndex);
|
|
PrintMoveInfo(itemId);
|
|
}
|
|
|
|
static void List_ItemPrintFunc(u8 windowId, u32 itemIndex, u8 y)
|
|
{
|
|
if (itemIndex != LIST_CANCEL)
|
|
{
|
|
u16 itemId = BagGetItemIdByPocketPosition(POCKET_TM_HM, itemIndex);
|
|
if (!IsItemHM(itemId))
|
|
{
|
|
if (!GetItemImportance(itemId))
|
|
{
|
|
ConvertIntToDecimalStringN(gStringVar1, BagGetQuantityByPocketPosition(POCKET_TM_HM, itemIndex), STR_CONV_MODE_RIGHT_ALIGN, 3);
|
|
StringExpandPlaceholders(gStringVar4, gText_TimesStrVar1);
|
|
}
|
|
else
|
|
{
|
|
StringCopy(gStringVar4, gText_EmptyString3);
|
|
}
|
|
TMCase_Print(windowId, FONT_SMALL, gStringVar4, 126, y, 0, 0, TEXT_SKIP_DRAW, COLOR_DARK);
|
|
}
|
|
else
|
|
{
|
|
PlaceHMTileInWindow(windowId, 8, y);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void PrintDescription(s32 itemIndex)
|
|
{
|
|
const u8 * str;
|
|
if (itemIndex != LIST_CANCEL)
|
|
str = GetItemDescription(BagGetItemIdByPocketPosition(POCKET_TM_HM, itemIndex));
|
|
else
|
|
str = gText_TMCaseWillBePutAway;
|
|
FillWindowPixelBuffer(WIN_DESCRIPTION, 0);
|
|
TMCase_Print(WIN_DESCRIPTION, FONT_NORMAL, str, 2, 3, 1, 0, 0, COLOR_LIGHT);
|
|
}
|
|
|
|
// Darkens (or subsequently lightens) the blue bg tiles around the description window when a TM/HM is selected.
|
|
// shade=0: lighten, shade=1: darken
|
|
static void SetDescriptionWindowShade(s32 shade)
|
|
{
|
|
SetBgTilemapPalette(2, 0, 12, 30, 8, 2 * shade + 1);
|
|
ScheduleBgCopyTilemapToVram(2);
|
|
}
|
|
|
|
static void PrintListCursor(u8 listTaskId, u8 colorIdx)
|
|
{
|
|
PrintListCursorAtRow(ListMenuGetYCoordForPrintingArrowCursor(listTaskId), colorIdx);
|
|
}
|
|
|
|
static void PrintListCursorAtRow(u8 y, u8 colorIdx)
|
|
{
|
|
if (colorIdx == COLOR_CURSOR_ERASE)
|
|
{
|
|
// Never used. Would erase cursor (but also a portion of the list text)
|
|
FillWindowPixelRect(WIN_LIST, 0, 0, y, GetFontAttribute(FONT_NORMAL, FONTATTR_MAX_LETTER_WIDTH), GetFontAttribute(FONT_NORMAL, FONTATTR_MAX_LETTER_HEIGHT));
|
|
CopyWindowToVram(WIN_LIST, COPYWIN_GFX);
|
|
}
|
|
else
|
|
{
|
|
TMCase_Print(WIN_LIST, FONT_NORMAL, gText_SelectorArrow2, 0, y, 0, 0, 0, colorIdx);
|
|
}
|
|
}
|
|
|
|
static void CreateListScrollArrows(void)
|
|
{
|
|
sTMCaseDynamicResources->scrollArrowsTaskId = AddScrollIndicatorArrowPairParameterized(SCROLL_ARROW_UP,
|
|
160, 8, 88,
|
|
sTMCaseDynamicResources->numTMs - sTMCaseDynamicResources->maxTMsShown + 1,
|
|
TAG_SCROLL_ARROW, TAG_SCROLL_ARROW,
|
|
&sTMCaseStaticResources.scrollOffset);
|
|
}
|
|
|
|
static void CreateQuantityScrollArrows(void)
|
|
{
|
|
sTMCaseDynamicResources->currItem = 1;
|
|
sTMCaseDynamicResources->scrollArrowsTaskId = AddScrollIndicatorArrowPairParameterized(SCROLL_ARROW_UP,
|
|
152, 72, 104,
|
|
2,
|
|
TAG_SCROLL_ARROW, TAG_SCROLL_ARROW,
|
|
&sTMCaseDynamicResources->currItem);
|
|
}
|
|
|
|
static void RemoveScrollArrows(void)
|
|
{
|
|
if (sTMCaseDynamicResources->scrollArrowsTaskId != TASK_NONE)
|
|
{
|
|
RemoveScrollIndicatorArrowPair(sTMCaseDynamicResources->scrollArrowsTaskId);
|
|
sTMCaseDynamicResources->scrollArrowsTaskId = TASK_NONE;
|
|
}
|
|
}
|
|
|
|
void ResetTMCaseCursorPos(void)
|
|
{
|
|
sTMCaseStaticResources.selectedRow = 0;
|
|
sTMCaseStaticResources.scrollOffset = 0;
|
|
}
|
|
|
|
static void TMCaseSetup_GetTMCount(void)
|
|
{
|
|
struct BagPocket * pocket = &gBagPockets[POCKET_TM_HM - 1];
|
|
u16 i;
|
|
|
|
BagPocketCompaction(pocket->itemSlots, pocket->capacity);
|
|
sTMCaseDynamicResources->numTMs = 0;
|
|
for (i = 0; i < pocket->capacity; i++)
|
|
{
|
|
if (pocket->itemSlots[i].itemId == ITEM_NONE)
|
|
break;
|
|
sTMCaseDynamicResources->numTMs++;
|
|
}
|
|
sTMCaseDynamicResources->maxTMsShown = min(sTMCaseDynamicResources->numTMs + 1, 5);
|
|
}
|
|
|
|
static void TMCaseSetup_InitListMenuPositions(void)
|
|
{
|
|
if (sTMCaseStaticResources.scrollOffset != 0)
|
|
{
|
|
if (sTMCaseStaticResources.scrollOffset + sTMCaseDynamicResources->maxTMsShown > sTMCaseDynamicResources->numTMs + 1)
|
|
sTMCaseStaticResources.scrollOffset = sTMCaseDynamicResources->numTMs + 1 - sTMCaseDynamicResources->maxTMsShown;
|
|
}
|
|
if (sTMCaseStaticResources.scrollOffset + sTMCaseStaticResources.selectedRow >= sTMCaseDynamicResources->numTMs + 1)
|
|
{
|
|
if (sTMCaseDynamicResources->numTMs + 1 < 2)
|
|
sTMCaseStaticResources.selectedRow = 0;
|
|
else
|
|
sTMCaseStaticResources.selectedRow = sTMCaseDynamicResources->numTMs;
|
|
}
|
|
}
|
|
|
|
static void TMCaseSetup_UpdateVisualMenuOffset(void)
|
|
{
|
|
u8 i;
|
|
if (sTMCaseStaticResources.selectedRow > 3)
|
|
{
|
|
for (i = 0; i <= sTMCaseStaticResources.selectedRow - 3 && sTMCaseStaticResources.scrollOffset + sTMCaseDynamicResources->maxTMsShown != sTMCaseDynamicResources->numTMs + 1; i++)
|
|
{
|
|
do {} while (0);
|
|
sTMCaseStaticResources.selectedRow--;
|
|
sTMCaseStaticResources.scrollOffset++;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void DestroyTMCaseBuffers(void)
|
|
{
|
|
if (sTMCaseDynamicResources != NULL)
|
|
Free(sTMCaseDynamicResources);
|
|
if (sTilemapBuffer != NULL)
|
|
Free(sTilemapBuffer);
|
|
if (sListMenuItemsBuffer != NULL)
|
|
Free(sListMenuItemsBuffer);
|
|
if (sListMenuStringsBuffer != NULL)
|
|
Free(sListMenuStringsBuffer);
|
|
FreeAllWindowBuffers();
|
|
}
|
|
|
|
static void Task_BeginFadeOutFromTMCase(u8 taskId)
|
|
{
|
|
BeginNormalPaletteFade(PALETTES_ALL, -2, 0, 16, RGB_BLACK);
|
|
gTasks[taskId].func = Task_FadeOutAndCloseTMCase;
|
|
}
|
|
|
|
static void Task_FadeOutAndCloseTMCase(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
|
|
if (!gPaletteFade.active)
|
|
{
|
|
DestroyListMenuTask(tListTaskId, &sTMCaseStaticResources.scrollOffset, &sTMCaseStaticResources.selectedRow);
|
|
if (sTMCaseDynamicResources->nextScreenCallback != NULL)
|
|
SetMainCallback2(sTMCaseDynamicResources->nextScreenCallback);
|
|
else
|
|
SetMainCallback2(sTMCaseStaticResources.exitCallback);
|
|
RemoveScrollArrows();
|
|
DestroyTMCaseBuffers();
|
|
DestroyTask(taskId);
|
|
}
|
|
}
|
|
|
|
static void Task_HandleListInput(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
s32 input;
|
|
|
|
if (!gPaletteFade.active)
|
|
{
|
|
if (IsActiveOverworldLinkBusy() != TRUE)
|
|
{
|
|
input = ListMenu_ProcessInput(tListTaskId);
|
|
ListMenuGetScrollAndRow(tListTaskId, &sTMCaseStaticResources.scrollOffset, &sTMCaseStaticResources.selectedRow);
|
|
if (JOY_NEW(SELECT_BUTTON) && sTMCaseStaticResources.allowSelectClose == TRUE)
|
|
{
|
|
PlaySE(SE_SELECT);
|
|
gSpecialVar_ItemId = ITEM_NONE;
|
|
Task_BeginFadeOutFromTMCase(taskId);
|
|
}
|
|
else
|
|
{
|
|
switch (input)
|
|
{
|
|
case LIST_NOTHING_CHOSEN:
|
|
break;
|
|
case LIST_CANCEL:
|
|
PlaySE(SE_SELECT);
|
|
gSpecialVar_ItemId = ITEM_NONE;
|
|
Task_BeginFadeOutFromTMCase(taskId);
|
|
break;
|
|
default:
|
|
PlaySE(SE_SELECT);
|
|
SetDescriptionWindowShade(1);
|
|
RemoveScrollArrows();
|
|
PrintListCursor(tListTaskId, COLOR_CURSOR_SELECTED);
|
|
tSelection = input;
|
|
tQuantityOwned = BagGetQuantityByPocketPosition(POCKET_TM_HM, input);
|
|
gSpecialVar_ItemId = BagGetItemIdByPocketPosition(POCKET_TM_HM, input);
|
|
gTasks[taskId].func = sSelectTMActionTasks[sTMCaseStaticResources.menuType];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void ReturnToList(u8 taskId)
|
|
{
|
|
SetDescriptionWindowShade(0);
|
|
CreateListScrollArrows();
|
|
gTasks[taskId].func = Task_HandleListInput;
|
|
}
|
|
|
|
// When a TM/HM in the list is selected in the field, create a context
|
|
// menu with a list of actions that can be taken.
|
|
static void Task_SelectedTMHM_Field(u8 taskId)
|
|
{
|
|
u8 * strbuf;
|
|
|
|
// Create context window
|
|
TMCase_SetWindowBorder2(WIN_SELECTED_MSG);
|
|
if (!MenuHelpers_IsLinkActive() && InUnionRoom() != TRUE)
|
|
{
|
|
// Regular TM/HM context menu
|
|
AddContextMenu(&sTMCaseDynamicResources->contextMenuWindowId, WIN_USE_GIVE_EXIT);
|
|
sTMCaseDynamicResources->menuActionIndices = sMenuActionIndices_Field;
|
|
sTMCaseDynamicResources->numMenuActions = ARRAY_COUNT(sMenuActionIndices_Field);
|
|
}
|
|
else
|
|
{
|
|
// In Union Room, "Use" is removed from the context menu
|
|
AddContextMenu(&sTMCaseDynamicResources->contextMenuWindowId, WIN_GIVE_EXIT);
|
|
sTMCaseDynamicResources->menuActionIndices = sMenuActionIndices_UnionRoom;
|
|
sTMCaseDynamicResources->numMenuActions = ARRAY_COUNT(sMenuActionIndices_UnionRoom);
|
|
}
|
|
|
|
// Print context window actions
|
|
PrintMenuActionTexts(sTMCaseDynamicResources->contextMenuWindowId,
|
|
FONT_NORMAL,
|
|
GetMenuCursorDimensionByFont(FONT_NORMAL, 0),
|
|
2,
|
|
0,
|
|
GetFontAttribute(FONT_NORMAL, FONTATTR_MAX_LETTER_HEIGHT) + 2,
|
|
sTMCaseDynamicResources->numMenuActions,
|
|
sMenuActions,
|
|
sTMCaseDynamicResources->menuActionIndices);
|
|
|
|
InitMenuNormal(sTMCaseDynamicResources->contextMenuWindowId, FONT_NORMAL, 0, 2, GetFontAttribute(FONT_NORMAL, FONTATTR_MAX_LETTER_HEIGHT) + 2, sTMCaseDynamicResources->numMenuActions, 0);
|
|
|
|
// Print label text next to the context window
|
|
strbuf = Alloc(256);
|
|
GetTMNumberAndMoveString(strbuf, gSpecialVar_ItemId);
|
|
StringAppend(strbuf, gText_Var1IsSelected + 2); // +2 skips over the stringvar
|
|
TMCase_Print(WIN_SELECTED_MSG, FONT_NORMAL, strbuf, 0, 2, 1, 0, 0, COLOR_DARK);
|
|
Free(strbuf);
|
|
if (IsItemHM(gSpecialVar_ItemId))
|
|
{
|
|
PlaceHMTileInWindow(WIN_SELECTED_MSG, 0, 2);
|
|
CopyWindowToVram(WIN_SELECTED_MSG, COPYWIN_GFX);
|
|
}
|
|
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
ScheduleBgCopyTilemapToVram(1);
|
|
gTasks[taskId].func = Task_ContextMenu_HandleInput;
|
|
}
|
|
|
|
static void Task_ContextMenu_HandleInput(u8 taskId)
|
|
{
|
|
s8 input;
|
|
|
|
if (IsActiveOverworldLinkBusy() != TRUE)
|
|
{
|
|
input = Menu_ProcessInputNoWrap();
|
|
switch (input)
|
|
{
|
|
case MENU_B_PRESSED:
|
|
// Run last action in list (Exit)
|
|
PlaySE(SE_SELECT);
|
|
sMenuActions[sTMCaseDynamicResources->menuActionIndices[sTMCaseDynamicResources->numMenuActions - 1]].func.void_u8(taskId);
|
|
break;
|
|
case MENU_NOTHING_CHOSEN:
|
|
break;
|
|
default:
|
|
PlaySE(SE_SELECT);
|
|
sMenuActions[sTMCaseDynamicResources->menuActionIndices[input]].func.void_u8(taskId);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void Action_Use(u8 taskId)
|
|
{
|
|
RemoveContextMenu(&sTMCaseDynamicResources->contextMenuWindowId);
|
|
ClearStdWindowAndFrameToTransparent(WIN_SELECTED_MSG, FALSE);
|
|
ClearWindowTilemap(WIN_SELECTED_MSG);
|
|
PutWindowTilemap(WIN_LIST);
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
ScheduleBgCopyTilemapToVram(1);
|
|
if (CalculatePlayerPartyCount() == 0)
|
|
{
|
|
PrintError_ThereIsNoPokemon(taskId);
|
|
}
|
|
else
|
|
{
|
|
// Chose a TM/HM to use, exit TM case for party menu
|
|
gItemUseCB = ItemUseCB_TMHM;
|
|
sTMCaseDynamicResources->nextScreenCallback = CB2_ShowPartyMenuForItemUse;
|
|
Task_BeginFadeOutFromTMCase(taskId);
|
|
}
|
|
}
|
|
|
|
static void Action_Give(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
u16 itemId = BagGetItemIdByPocketPosition(POCKET_TM_HM, tSelection);
|
|
RemoveContextMenu(&sTMCaseDynamicResources->contextMenuWindowId);
|
|
ClearStdWindowAndFrameToTransparent(WIN_SELECTED_MSG, FALSE);
|
|
ClearWindowTilemap(WIN_SELECTED_MSG);
|
|
PutWindowTilemap(WIN_DESCRIPTION);
|
|
PutWindowTilemap(WIN_MOVE_INFO_LABELS);
|
|
PutWindowTilemap(WIN_MOVE_INFO);
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
ScheduleBgCopyTilemapToVram(1);
|
|
if (!GetItemImportance(itemId))
|
|
{
|
|
if (CalculatePlayerPartyCount() == 0)
|
|
{
|
|
PrintError_ThereIsNoPokemon(taskId);
|
|
}
|
|
else
|
|
{
|
|
sTMCaseDynamicResources->nextScreenCallback = CB2_ChooseMonToGiveItem;
|
|
Task_BeginFadeOutFromTMCase(taskId);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PrintError_ItemCantBeHeld(taskId);
|
|
}
|
|
}
|
|
|
|
static void PrintError_ThereIsNoPokemon(u8 taskId)
|
|
{
|
|
PrintMessageWithFollowupTask(taskId, FONT_NORMAL, gText_ThereIsNoPokemon, Task_WaitButtonAfterErrorPrint);
|
|
}
|
|
|
|
static void PrintError_ItemCantBeHeld(u8 taskId)
|
|
{
|
|
CopyItemName(gSpecialVar_ItemId, gStringVar1);
|
|
StringExpandPlaceholders(gStringVar4, gText_ItemCantBeHeld);
|
|
PrintMessageWithFollowupTask(taskId, FONT_NORMAL, gStringVar4, Task_WaitButtonAfterErrorPrint);
|
|
}
|
|
|
|
static void Task_WaitButtonAfterErrorPrint(u8 taskId)
|
|
{
|
|
if (JOY_NEW(A_BUTTON))
|
|
{
|
|
PlaySE(SE_SELECT);
|
|
CloseMessageAndReturnToList(taskId);
|
|
}
|
|
}
|
|
|
|
static void CloseMessageAndReturnToList(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
|
|
DestroyListMenuTask(tListTaskId, &sTMCaseStaticResources.scrollOffset, &sTMCaseStaticResources.selectedRow);
|
|
tListTaskId = ListMenuInit(&gMultiuseListMenuTemplate, sTMCaseStaticResources.scrollOffset, sTMCaseStaticResources.selectedRow);
|
|
PrintListCursor(tListTaskId, COLOR_DARK);
|
|
ClearDialogWindowAndFrameToTransparent(WIN_MESSAGE, FALSE);
|
|
ClearWindowTilemap(WIN_MESSAGE);
|
|
PutWindowTilemap(WIN_DESCRIPTION);
|
|
PutWindowTilemap(WIN_MOVE_INFO_LABELS);
|
|
PutWindowTilemap(WIN_MOVE_INFO);
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
ScheduleBgCopyTilemapToVram(1);
|
|
ReturnToList(taskId);
|
|
}
|
|
|
|
static void Action_Exit(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
|
|
RemoveContextMenu(&sTMCaseDynamicResources->contextMenuWindowId);
|
|
ClearStdWindowAndFrameToTransparent(WIN_SELECTED_MSG, FALSE);
|
|
ClearWindowTilemap(WIN_SELECTED_MSG);
|
|
PutWindowTilemap(WIN_LIST);
|
|
PrintListCursor(tListTaskId, COLOR_DARK);
|
|
PutWindowTilemap(WIN_DESCRIPTION);
|
|
PutWindowTilemap(WIN_MOVE_INFO_LABELS);
|
|
PutWindowTilemap(WIN_MOVE_INFO);
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
ScheduleBgCopyTilemapToVram(1);
|
|
ReturnToList(taskId);
|
|
}
|
|
|
|
static void Task_SelectedTMHM_GiveParty(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
|
|
if (!GetItemImportance(BagGetItemIdByPocketPosition(POCKET_TM_HM, tSelection)))
|
|
{
|
|
sTMCaseDynamicResources->nextScreenCallback = CB2_GiveHoldItem;
|
|
Task_BeginFadeOutFromTMCase(taskId);
|
|
}
|
|
else
|
|
{
|
|
// Can't hold "important" items (e.g. key items)
|
|
PrintError_ItemCantBeHeld(taskId);
|
|
}
|
|
}
|
|
|
|
static void Task_SelectedTMHM_GivePC(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
|
|
if (!GetItemImportance(BagGetItemIdByPocketPosition(POCKET_TM_HM, tSelection)))
|
|
{
|
|
sTMCaseDynamicResources->nextScreenCallback = CB2_ReturnToPokeStorage;
|
|
Task_BeginFadeOutFromTMCase(taskId);
|
|
}
|
|
else
|
|
{
|
|
// Can't hold "important" items (e.g. key items)
|
|
PrintError_ItemCantBeHeld(taskId);
|
|
}
|
|
}
|
|
|
|
static void Task_SelectedTMHM_Sell(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
|
|
if (GetItemImportance(gSpecialVar_ItemId))
|
|
{
|
|
// Can't sell TM/HMs with no price (by default this is just the HMs)
|
|
CopyItemName(gSpecialVar_ItemId, gStringVar1);
|
|
StringExpandPlaceholders(gStringVar4, gText_OhNoICantBuyThat);
|
|
PrintMessageWithFollowupTask(taskId, GetDialogBoxFontId(), gStringVar4, CloseMessageAndReturnToList);
|
|
}
|
|
else
|
|
{
|
|
tQuantitySelected = 1;
|
|
if (tQuantityOwned == 1)
|
|
{
|
|
PrintPlayersMoney();
|
|
Task_AskConfirmSaleWithAmount(taskId);
|
|
}
|
|
else
|
|
{
|
|
if (tQuantityOwned > 99)
|
|
tQuantityOwned = 99;
|
|
CopyItemName(gSpecialVar_ItemId, gStringVar1);
|
|
StringExpandPlaceholders(gStringVar4, gText_HowManyWouldYouLikeToSell);
|
|
PrintMessageWithFollowupTask(taskId, GetDialogBoxFontId(), gStringVar4, Task_InitQuantitySelectUI);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void Task_AskConfirmSaleWithAmount(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
|
|
ConvertIntToDecimalStringN(gStringVar3, GetItemPrice(BagGetItemIdByPocketPosition(POCKET_TM_HM, tSelection)) / 2 * tQuantitySelected, STR_CONV_MODE_LEFT_ALIGN, 6);
|
|
StringExpandPlaceholders(gStringVar4, gText_ICanPayThisMuch_WouldThatBeOkay);
|
|
PrintMessageWithFollowupTask(taskId, GetDialogBoxFontId(), gStringVar4, Task_PlaceYesNoBox);
|
|
}
|
|
|
|
static void Task_PlaceYesNoBox(u8 taskId)
|
|
{
|
|
HandleCreateYesNoMenu(taskId, &sYesNoFuncTable);
|
|
}
|
|
|
|
static void Task_SaleOfTMsCanceled(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
|
|
ClearStdWindowAndFrameToTransparent(WIN_MONEY, FALSE);
|
|
ClearDialogWindowAndFrameToTransparent(WIN_MESSAGE, FALSE);
|
|
PutWindowTilemap(WIN_LIST);
|
|
PutWindowTilemap(WIN_DESCRIPTION);
|
|
PutWindowTilemap(WIN_TITLE);
|
|
PutWindowTilemap(WIN_MOVE_INFO_LABELS);
|
|
PutWindowTilemap(WIN_MOVE_INFO);
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
ScheduleBgCopyTilemapToVram(1);
|
|
PrintListCursor(tListTaskId, COLOR_DARK);
|
|
ReturnToList(taskId);
|
|
}
|
|
|
|
static void Task_InitQuantitySelectUI(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
|
|
TMCase_SetWindowBorder1(WIN_SELL_QUANTITY);
|
|
ConvertIntToDecimalStringN(gStringVar1, 1, STR_CONV_MODE_LEADING_ZEROS, 2);
|
|
StringExpandPlaceholders(gStringVar4, gText_TimesStrVar1);
|
|
TMCase_Print(WIN_SELL_QUANTITY, FONT_SMALL, gStringVar4, 4, 10, 1, 0, 0, COLOR_DARK);
|
|
SellTM_PrintQuantityAndSalePrice(1, GetItemPrice(BagGetItemIdByPocketPosition(POCKET_TM_HM, tSelection)) / 2 * tQuantitySelected);
|
|
PrintPlayersMoney();
|
|
CreateQuantityScrollArrows();
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
ScheduleBgCopyTilemapToVram(1);
|
|
gTasks[taskId].func = Task_QuantitySelect_HandleInput;
|
|
}
|
|
|
|
static void SellTM_PrintQuantityAndSalePrice(s16 quantity, s32 amount)
|
|
{
|
|
FillWindowPixelBuffer(WIN_SELL_QUANTITY, 0x11);
|
|
ConvertIntToDecimalStringN(gStringVar1, quantity, STR_CONV_MODE_LEADING_ZEROS, 2);
|
|
StringExpandPlaceholders(gStringVar4, gText_TimesStrVar1);
|
|
TMCase_Print(WIN_SELL_QUANTITY, FONT_SMALL, gStringVar4, 4, 10, 1, 0, 0, COLOR_DARK);
|
|
PrintMoneyAmount(WIN_SELL_QUANTITY, 0x38, 0x0A, amount, 0);
|
|
}
|
|
|
|
static void Task_QuantitySelect_HandleInput(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
|
|
if (AdjustQuantityAccordingToDPadInput(&tQuantitySelected, tQuantityOwned) == 1)
|
|
{
|
|
SellTM_PrintQuantityAndSalePrice(tQuantitySelected, GetItemPrice(BagGetItemIdByPocketPosition(POCKET_TM_HM, tSelection)) / 2 * tQuantitySelected);
|
|
}
|
|
else if (JOY_NEW(A_BUTTON))
|
|
{
|
|
PlaySE(SE_SELECT);
|
|
ClearStdWindowAndFrameToTransparent(WIN_SELL_QUANTITY, FALSE);
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
ScheduleBgCopyTilemapToVram(1);
|
|
RemoveScrollArrows();
|
|
Task_AskConfirmSaleWithAmount(taskId);
|
|
}
|
|
else if (JOY_NEW(B_BUTTON))
|
|
{
|
|
PlaySE(SE_SELECT);
|
|
ClearStdWindowAndFrameToTransparent(WIN_SELL_QUANTITY, FALSE);
|
|
ClearStdWindowAndFrameToTransparent(WIN_MONEY, FALSE);
|
|
ClearDialogWindowAndFrameToTransparent(WIN_MESSAGE, FALSE);
|
|
PutWindowTilemap(WIN_TITLE);
|
|
PutWindowTilemap(WIN_LIST);
|
|
PutWindowTilemap(WIN_DESCRIPTION);
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
ScheduleBgCopyTilemapToVram(1);
|
|
RemoveScrollArrows();
|
|
PrintListCursor(tListTaskId, COLOR_DARK);
|
|
ReturnToList(taskId);
|
|
}
|
|
}
|
|
|
|
static void Task_PrintSaleConfirmedText(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
|
|
PutWindowTilemap(WIN_LIST);
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
CopyItemName(gSpecialVar_ItemId, gStringVar1);
|
|
ConvertIntToDecimalStringN(gStringVar3, GetItemPrice(BagGetItemIdByPocketPosition(POCKET_TM_HM, tSelection)) / 2 * tQuantitySelected, STR_CONV_MODE_LEFT_ALIGN, 6);
|
|
StringExpandPlaceholders(gStringVar4, gText_TurnedOverItemsWorthYen);
|
|
PrintMessageWithFollowupTask(taskId, FONT_NORMAL, gStringVar4, Task_DoSaleOfTMs);
|
|
}
|
|
|
|
static void Task_DoSaleOfTMs(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
|
|
PlaySE(SE_SHOP);
|
|
RemoveBagItem(gSpecialVar_ItemId, tQuantitySelected);
|
|
AddMoney(&gSaveBlock1Ptr->money, GetItemPrice(gSpecialVar_ItemId) / 2 * tQuantitySelected);
|
|
RecordItemTransaction(gSpecialVar_ItemId, tQuantitySelected, QL_EVENT_SOLD_ITEM - QL_EVENT_USED_POKEMART);
|
|
DestroyListMenuTask(tListTaskId, &sTMCaseStaticResources.scrollOffset, &sTMCaseStaticResources.selectedRow);
|
|
TMCaseSetup_GetTMCount();
|
|
TMCaseSetup_InitListMenuPositions();
|
|
InitTMCaseListMenuItems();
|
|
tListTaskId = ListMenuInit(&gMultiuseListMenuTemplate, sTMCaseStaticResources.scrollOffset, sTMCaseStaticResources.selectedRow);
|
|
PrintListCursor(tListTaskId, COLOR_CURSOR_SELECTED);
|
|
PrintMoneyAmountInMoneyBox(WIN_MONEY, GetMoney(&gSaveBlock1Ptr->money), 0);
|
|
gTasks[taskId].func = Task_AfterSale_ReturnToList;
|
|
}
|
|
|
|
static void Task_AfterSale_ReturnToList(u8 taskId)
|
|
{
|
|
if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON))
|
|
{
|
|
PlaySE(SE_SELECT);
|
|
ClearStdWindowAndFrameToTransparent(WIN_MONEY, FALSE);
|
|
ClearDialogWindowAndFrameToTransparent(WIN_MESSAGE, FALSE);
|
|
PutWindowTilemap(WIN_DESCRIPTION);
|
|
PutWindowTilemap(WIN_TITLE);
|
|
PutWindowTilemap(WIN_MOVE_INFO_LABELS);
|
|
PutWindowTilemap(WIN_MOVE_INFO);
|
|
CloseMessageAndReturnToList(taskId);
|
|
}
|
|
}
|
|
|
|
void Pokedude_InitTMCase(void)
|
|
{
|
|
sPokedudeBagBackup = AllocZeroed(sizeof(*sPokedudeBagBackup));
|
|
memcpy(sPokedudeBagBackup->bagPocket_TMHM, gSaveBlock1Ptr->bagPocket_TMHM, sizeof(gSaveBlock1Ptr->bagPocket_TMHM));
|
|
memcpy(sPokedudeBagBackup->bagPocket_KeyItems, gSaveBlock1Ptr->bagPocket_KeyItems, sizeof(gSaveBlock1Ptr->bagPocket_KeyItems));
|
|
sPokedudeBagBackup->selectedRow = sTMCaseStaticResources.selectedRow;
|
|
sPokedudeBagBackup->scrollOffset = sTMCaseStaticResources.scrollOffset;
|
|
ClearItemSlots(gSaveBlock1Ptr->bagPocket_TMHM, ARRAY_COUNT(gSaveBlock1Ptr->bagPocket_TMHM));
|
|
ClearItemSlots(gSaveBlock1Ptr->bagPocket_KeyItems, ARRAY_COUNT(gSaveBlock1Ptr->bagPocket_KeyItems));
|
|
ResetTMCaseCursorPos();
|
|
AddBagItem(ITEM_TM01, 1);
|
|
AddBagItem(ITEM_TM03, 1);
|
|
AddBagItem(ITEM_TM09, 1);
|
|
AddBagItem(ITEM_TM35, 1);
|
|
InitTMCase(TMCASE_POKEDUDE, CB2_ReturnToTeachyTV, 0);
|
|
}
|
|
|
|
static void Task_Pokedude_Start(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
|
|
if (!gPaletteFade.active)
|
|
{
|
|
tPokedudeState = 0;
|
|
tPokedudeTimer = 0;
|
|
gTasks[taskId].func = Task_Pokedude_Run;
|
|
}
|
|
}
|
|
|
|
#define POKEDUDE_INPUT_DELAY 101
|
|
|
|
static void Task_Pokedude_Run(u8 taskId)
|
|
{
|
|
s16 * data = gTasks[taskId].data;
|
|
|
|
if (JOY_NEW(B_BUTTON))
|
|
{
|
|
if (tPokedudeState < 21)
|
|
{
|
|
tPokedudeState = 21;
|
|
SetTeachyTvControllerModeToResume();
|
|
}
|
|
}
|
|
|
|
switch (tPokedudeState)
|
|
{
|
|
case 0:
|
|
BeginNormalPaletteFade(0xFFFF8405, 4, 0, 6, 0);
|
|
SetDescriptionWindowShade(1);
|
|
tPokedudeState++;
|
|
break;
|
|
case 1:
|
|
case 11:
|
|
if (!gPaletteFade.active)
|
|
{
|
|
if (++tPokedudeTimer > POKEDUDE_INPUT_DELAY)
|
|
{
|
|
tPokedudeTimer = 0;
|
|
tPokedudeState++;
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 12:
|
|
case 13:
|
|
case 14:
|
|
if (tPokedudeTimer == 0)
|
|
{
|
|
gMain.newKeys = 0;
|
|
gMain.newAndRepeatedKeys = DPAD_DOWN;
|
|
ListMenu_ProcessInput(tListTaskId);
|
|
}
|
|
if (++tPokedudeTimer > POKEDUDE_INPUT_DELAY)
|
|
{
|
|
tPokedudeTimer = 0;
|
|
tPokedudeState++;
|
|
}
|
|
break;
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 15:
|
|
case 16:
|
|
case 17:
|
|
if (tPokedudeTimer == 0)
|
|
{
|
|
gMain.newKeys = 0;
|
|
gMain.newAndRepeatedKeys = DPAD_UP;
|
|
ListMenu_ProcessInput(tListTaskId);
|
|
}
|
|
if (++tPokedudeTimer > POKEDUDE_INPUT_DELAY)
|
|
{
|
|
tPokedudeTimer = 0;
|
|
tPokedudeState++;
|
|
}
|
|
break;
|
|
case 8:
|
|
SetDescriptionWindowShade(1);
|
|
PrintMessageWithFollowupTask(taskId, FONT_MALE, gPokedudeText_TMTypes, NULL);
|
|
gTasks[taskId].func = Task_Pokedude_Run;
|
|
tPokedudeState++;
|
|
break;
|
|
case 9:
|
|
case 19:
|
|
RunTextPrinters();
|
|
if (!IsTextPrinterActive(WIN_MESSAGE))
|
|
tPokedudeState++;
|
|
break;
|
|
case 10:
|
|
if (JOY_NEW(A_BUTTON | B_BUTTON))
|
|
{
|
|
SetDescriptionWindowShade(0);
|
|
BeginNormalPaletteFade(0x00000400, 0, 6, 0, 0);
|
|
ClearDialogWindowAndFrameToTransparent(WIN_MESSAGE, FALSE);
|
|
ScheduleBgCopyTilemapToVram(1);
|
|
tPokedudeState++;
|
|
}
|
|
break;
|
|
case 18:
|
|
SetDescriptionWindowShade(1);
|
|
PrintMessageWithFollowupTask(taskId, FONT_MALE, gPokedudeText_ReadTMDescription, NULL);
|
|
gTasks[taskId].func = Task_Pokedude_Run; // this function
|
|
tPokedudeState++;
|
|
break;
|
|
case 20:
|
|
if (JOY_NEW(A_BUTTON | B_BUTTON))
|
|
tPokedudeState++;
|
|
break;
|
|
case 21:
|
|
if (!gPaletteFade.active)
|
|
{
|
|
// Restore the player's bag
|
|
memcpy(gSaveBlock1Ptr->bagPocket_TMHM, sPokedudeBagBackup->bagPocket_TMHM, sizeof(gSaveBlock1Ptr->bagPocket_TMHM));
|
|
memcpy(gSaveBlock1Ptr->bagPocket_KeyItems, sPokedudeBagBackup->bagPocket_KeyItems, sizeof(gSaveBlock1Ptr->bagPocket_KeyItems));
|
|
DestroyListMenuTask(tListTaskId, NULL, NULL);
|
|
sTMCaseStaticResources.selectedRow = sPokedudeBagBackup->selectedRow;
|
|
sTMCaseStaticResources.scrollOffset = sPokedudeBagBackup->scrollOffset;
|
|
Free(sPokedudeBagBackup);
|
|
CpuFastCopy(gPlttBufferFaded, gPlttBufferUnfaded, PLTT_SIZE);
|
|
SetBagOpenFalse();
|
|
BeginNormalPaletteFade(PALETTES_ALL, -2, 0, 16, 0);
|
|
tPokedudeState++;
|
|
}
|
|
break;
|
|
default:
|
|
if (!gPaletteFade.active)
|
|
{
|
|
SetMainCallback2(sTMCaseStaticResources.exitCallback);
|
|
RemoveScrollArrows();
|
|
DestroyTMCaseBuffers();
|
|
DestroyTask(taskId);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void InitWindowTemplatesAndPals(void)
|
|
{
|
|
u8 i;
|
|
|
|
InitWindows(sWindowTemplates);
|
|
DeactivateAllTextPrinters();
|
|
LoadUserWindowBorderGfx(0, 0x5B, BG_PLTT_ID(14));
|
|
LoadMessageBoxGfx(0, 0x64, BG_PLTT_ID(11));
|
|
LoadStdWindowGfx(0, 0x78, BG_PLTT_ID(13));
|
|
LoadPalette(gStandardMenuPalette, BG_PLTT_ID(15), PLTT_SIZE_4BPP);
|
|
LoadPalette(gStandardMenuPalette, BG_PLTT_ID(10), PLTT_SIZE_4BPP);
|
|
LoadPalette(sPal3Override, BG_PLTT_ID(15) + 6, sizeof(sPal3Override));
|
|
LoadPalette(sPal3Override, BG_PLTT_ID(13) + 6, sizeof(sPal3Override));
|
|
ListMenuLoadStdPalAt(BG_PLTT_ID(12), 1);
|
|
for (i = 0; i < ARRAY_COUNT(sWindowTemplates) - 1; i++)
|
|
FillWindowPixelBuffer(i, 0x00);
|
|
PutWindowTilemap(WIN_LIST);
|
|
PutWindowTilemap(WIN_DESCRIPTION);
|
|
PutWindowTilemap(WIN_TITLE);
|
|
PutWindowTilemap(WIN_MOVE_INFO_LABELS);
|
|
PutWindowTilemap(WIN_MOVE_INFO);
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
}
|
|
|
|
static void TMCase_Print(u8 windowId, u8 fontId, const u8 * str, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, u8 speed, u8 colorIdx)
|
|
{
|
|
AddTextPrinterParameterized4(windowId, fontId, x, y, letterSpacing, lineSpacing, sTextColors[colorIdx], speed, str);
|
|
}
|
|
|
|
static void TMCase_SetWindowBorder1(u8 windowId)
|
|
{
|
|
DrawStdFrameWithCustomTileAndPalette(windowId, FALSE, 0x5B, 14);
|
|
}
|
|
|
|
static void TMCase_SetWindowBorder2(u8 windowId)
|
|
{
|
|
DrawStdFrameWithCustomTileAndPalette(windowId, FALSE, 0x78, 13);
|
|
}
|
|
|
|
static void PrintMessageWithFollowupTask(u8 taskId, u8 fontId, const u8 * str, TaskFunc func)
|
|
{
|
|
DisplayMessageAndContinueTask(taskId, WIN_MESSAGE, 0x64, 0x0B, fontId, GetPlayerTextSpeedDelay(), str, func);
|
|
ScheduleBgCopyTilemapToVram(1);
|
|
}
|
|
|
|
static void PrintTitle(void)
|
|
{
|
|
u32 distance = 72 - GetStringWidth(FONT_NORMAL_COPY_1, gText_TMCase, 0);
|
|
AddTextPrinterParameterized3(WIN_TITLE, FONT_NORMAL_COPY_1, distance / 2, 1, sTextColors[COLOR_LIGHT], 0, gText_TMCase);
|
|
}
|
|
|
|
static void DrawMoveInfoLabels(void)
|
|
{
|
|
BlitMenuInfoIcon(WIN_MOVE_INFO_LABELS, MENU_INFO_ICON_TYPE, 0, 0);
|
|
BlitMenuInfoIcon(WIN_MOVE_INFO_LABELS, MENU_INFO_ICON_POWER, 0, 12);
|
|
BlitMenuInfoIcon(WIN_MOVE_INFO_LABELS, MENU_INFO_ICON_ACCURACY, 0, 24);
|
|
BlitMenuInfoIcon(WIN_MOVE_INFO_LABELS, MENU_INFO_ICON_PP, 0, 36);
|
|
CopyWindowToVram(WIN_MOVE_INFO_LABELS, COPYWIN_GFX);
|
|
}
|
|
|
|
static void PrintMoveInfo(u16 itemId)
|
|
{
|
|
u8 i;
|
|
u16 move;
|
|
const u8 * str;
|
|
|
|
FillWindowPixelRect(WIN_MOVE_INFO, 0, 0, 0, 40, 48);
|
|
if (itemId == ITEM_NONE)
|
|
{
|
|
for (i = 0; i < 4; i++)
|
|
TMCase_Print(WIN_MOVE_INFO, FONT_NORMAL_COPY_2, gText_ThreeHyphens, 7, 12 * i, 0, 0, TEXT_SKIP_DRAW, COLOR_MOVE_INFO);
|
|
CopyWindowToVram(WIN_MOVE_INFO, COPYWIN_GFX);
|
|
}
|
|
else
|
|
{
|
|
// Draw type icon
|
|
move = ItemIdToBattleMoveId(itemId);
|
|
BlitMenuInfoIcon(WIN_MOVE_INFO, gMovesInfo[move].type + 1, 0, 0);
|
|
|
|
// Print power
|
|
if (gMovesInfo[move].power < 2)
|
|
str = gText_ThreeHyphens;
|
|
else
|
|
{
|
|
ConvertIntToDecimalStringN(gStringVar1, gMovesInfo[move].power, STR_CONV_MODE_RIGHT_ALIGN, 3);
|
|
str = gStringVar1;
|
|
}
|
|
TMCase_Print(WIN_MOVE_INFO, FONT_NORMAL_COPY_2, str, 7, 12, 0, 0, TEXT_SKIP_DRAW, COLOR_MOVE_INFO);
|
|
|
|
// Print accuracy
|
|
if (gMovesInfo[move].accuracy == 0)
|
|
str = gText_ThreeHyphens;
|
|
else
|
|
{
|
|
ConvertIntToDecimalStringN(gStringVar1, gMovesInfo[move].accuracy, STR_CONV_MODE_RIGHT_ALIGN, 3);
|
|
str = gStringVar1;
|
|
}
|
|
TMCase_Print(WIN_MOVE_INFO, FONT_NORMAL_COPY_2, str, 7, 24, 0, 0, TEXT_SKIP_DRAW, COLOR_MOVE_INFO);
|
|
|
|
// Print PP
|
|
ConvertIntToDecimalStringN(gStringVar1, gMovesInfo[move].pp, STR_CONV_MODE_RIGHT_ALIGN, 3);
|
|
TMCase_Print(WIN_MOVE_INFO, FONT_NORMAL_COPY_2, gStringVar1, 7, 36, 0, 0, TEXT_SKIP_DRAW, COLOR_MOVE_INFO);
|
|
|
|
CopyWindowToVram(WIN_MOVE_INFO, COPYWIN_GFX);
|
|
}
|
|
}
|
|
|
|
static void PlaceHMTileInWindow(u8 windowId, u8 x, u8 y)
|
|
{
|
|
BlitBitmapToWindow(windowId, gTMCaseHM_Gfx, x, y, 16, 12);
|
|
}
|
|
|
|
static void PrintPlayersMoney(void)
|
|
{
|
|
PrintMoneyAmountInMoneyBoxWithBorder(WIN_MONEY, 120, 13, GetMoney(&gSaveBlock1Ptr->money));
|
|
}
|
|
|
|
static void HandleCreateYesNoMenu(u8 taskId, const struct YesNoFuncTable *ptrs)
|
|
{
|
|
CreateYesNoMenuWithCallbacks(taskId, &sYesNoWindowTemplate, FONT_NORMAL, 0, 2, 91, 14, ptrs);
|
|
}
|
|
|
|
static u8 AddContextMenu(u8 * windowId, u8 windowIndex)
|
|
{
|
|
if (*windowId == WINDOW_NONE)
|
|
{
|
|
*windowId = AddWindow(&sWindowTemplates_ContextMenu[windowIndex]);
|
|
TMCase_SetWindowBorder1(*windowId);
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
}
|
|
return *windowId;
|
|
}
|
|
|
|
static void RemoveContextMenu(u8 * windowId)
|
|
{
|
|
ClearStdWindowAndFrameToTransparent(*windowId, FALSE);
|
|
ClearWindowTilemap(*windowId);
|
|
RemoveWindow(*windowId);
|
|
ScheduleBgCopyTilemapToVram(0);
|
|
*windowId = WINDOW_NONE;
|
|
}
|
|
|
|
static u8 CreateDiscSprite(u16 itemId)
|
|
{
|
|
u8 spriteId = CreateSprite(&sSpriteTemplate_Disc, DISC_BASE_X, DISC_BASE_Y, 0);
|
|
u8 tmIdx;
|
|
if (itemId == ITEM_NONE)
|
|
{
|
|
SetDiscSpritePosition(&gSprites[spriteId], DISC_HIDDEN);
|
|
return spriteId;
|
|
}
|
|
else
|
|
{
|
|
tmIdx = itemId - ITEM_TM01;
|
|
SetDiscSpriteAnim(&gSprites[spriteId], tmIdx);
|
|
TintDiscpriteByType(gMovesInfo[ItemIdToBattleMoveId(itemId)].type);
|
|
SetDiscSpritePosition(&gSprites[spriteId], tmIdx);
|
|
return spriteId;
|
|
}
|
|
}
|
|
|
|
static void SetDiscSpriteAnim(struct Sprite *sprite, u8 tmIdx)
|
|
{
|
|
if (tmIdx >= NUM_TECHNICAL_MACHINES)
|
|
StartSpriteAnim(sprite, ANIM_HM);
|
|
else
|
|
StartSpriteAnim(sprite, ANIM_TM);
|
|
}
|
|
|
|
#define NUM_TYPES_PER_PALETTE 16
|
|
|
|
static void TintDiscpriteByType(u8 type)
|
|
{
|
|
u8 palOffset = PLTT_ID(IndexOfSpritePaletteTag(TAG_DISC));
|
|
u32 palTypeIndex = sTMSpritePaletteOffsetByType[type] / (NUM_TYPES_PER_PALETTE * PLTT_SIZE_4BPP);
|
|
u32 palTypeOffset = sTMSpritePaletteOffsetByType[type] % (NUM_TYPES_PER_PALETTE * PLTT_SIZE_4BPP);
|
|
|
|
LoadPalette(&gTMCaseDiscTypes_Pal[palTypeIndex][palTypeOffset], OBJ_PLTT_OFFSET + palOffset, PLTT_SIZE_4BPP);
|
|
if (sTMCaseStaticResources.menuType == TMCASE_POKEDUDE)
|
|
BlendPalettes(1 << (16 + palOffset), 4, RGB_BLACK);
|
|
}
|
|
|
|
static void SetDiscSpritePosition(struct Sprite *sprite, u8 tmIdx)
|
|
{
|
|
s32 x, y;
|
|
if (tmIdx == DISC_HIDDEN)
|
|
{
|
|
x = 27;
|
|
y = 54;
|
|
sprite->y2 = DISC_CASE_DISTANCE;
|
|
}
|
|
else
|
|
{
|
|
if (tmIdx >= NUM_TECHNICAL_MACHINES)
|
|
tmIdx -= NUM_TECHNICAL_MACHINES;
|
|
else
|
|
tmIdx += NUM_HIDDEN_MACHINES;
|
|
|
|
x = DISC_BASE_X - Q_24_8_TO_INT(Q_24_8(14 * tmIdx) / (NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES));
|
|
y = DISC_BASE_Y + Q_24_8_TO_INT(Q_24_8(8 * tmIdx) / (NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES));
|
|
}
|
|
sprite->x = x;
|
|
sprite->y = y;
|
|
}
|
|
|
|
#define sItemId data[0]
|
|
#define sState data[1]
|
|
|
|
static void SwapDisc(u8 spriteId, u16 itemId)
|
|
{
|
|
gSprites[spriteId].sItemId = itemId;
|
|
gSprites[spriteId].sState = 0;
|
|
gSprites[spriteId].callback = SpriteCB_SwapDisc;
|
|
}
|
|
|
|
static void SpriteCB_SwapDisc(struct Sprite *sprite)
|
|
{
|
|
switch (sprite->sState)
|
|
{
|
|
case 0:
|
|
// Lower old disc back into case
|
|
if (sprite->y2 >= DISC_CASE_DISTANCE)
|
|
{
|
|
// Old disc is hidden, set up new disc
|
|
if (sprite->sItemId != ITEM_NONE)
|
|
{
|
|
sprite->sState++;
|
|
TintDiscpriteByType(gMovesInfo[ItemIdToBattleMoveId(sprite->sItemId)].type);
|
|
sprite->sItemId -= ITEM_TM01;
|
|
SetDiscSpriteAnim(sprite, sprite->sItemId);
|
|
SetDiscSpritePosition(sprite, sprite->sItemId);
|
|
}
|
|
else
|
|
sprite->callback = SpriteCallbackDummy;
|
|
}
|
|
else
|
|
{
|
|
sprite->y2 += DISC_Y_MOVE;
|
|
}
|
|
break;
|
|
case 1:
|
|
// Raise new disc out of case
|
|
if (sprite->y2 <= 0)
|
|
sprite->callback = SpriteCallbackDummy;
|
|
else
|
|
sprite->y2 -= DISC_Y_MOVE;
|
|
}
|
|
}
|