Files
PokemonEmeraldSafariFrontier/src/decoration.c
aaaaaa123456789 7dc95a0103 Undo PokeCodec's PRs
This commit undoes most of PokeCodec's PRs after the debate in chat. Some
harmless or completely superseded PRs have been left alone, as there is not
much benefit in attempting to undo them.

Reverts #1104, #1108, #1115, #1118, #1119, #1124, #1126, #1127, #1132, #1136,
#1137, #1139, #1140, #1144, #1148, #1149, #1150, #1153, #1155, #1177, #1179,
#1180, #1181, #1182 and #1183.
2020-09-13 06:30:55 -03:00

2722 lines
85 KiB
C

#include "global.h"
#include "malloc.h"
#include "decompress.h"
#include "decoration.h"
#include "decoration_inventory.h"
#include "event_data.h"
#include "event_object_movement.h"
#include "event_scripts.h"
#include "field_camera.h"
#include "field_player_avatar.h"
#include "field_screen_effect.h"
#include "field_weather.h"
#include "fieldmap.h"
#include "graphics.h"
#include "international_string_util.h"
#include "item_icon.h"
#include "item_menu.h"
#include "list_menu.h"
#include "main.h"
#include "menu.h"
#include "menu_helpers.h"
#include "metatile_behavior.h"
#include "overworld.h"
#include "palette.h"
#include "player_pc.h"
#include "script.h"
#include "secret_base.h"
#include "sound.h"
#include "string_util.h"
#include "strings.h"
#include "task.h"
#include "text.h"
#include "tilesets.h"
#include "trader.h"
#include "tv.h"
#include "constants/decorations.h"
#include "constants/event_objects.h"
#include "constants/songs.h"
#include "constants/region_map_sections.h"
#include "constants/metatile_labels.h"
#define PLACE_DECORATION_SELECTOR_TAG 0xbe5
#define PLACE_DECORATION_PLAYER_TAG 0x008
#define NUM_DECORATION_FLAGS (FLAG_DECORATION_14 - FLAG_DECORATION_0)
#define tCursorX data[0]
#define tCursorY data[1]
#define tState data[2]
#define tInitialX data[3]
#define tInitialY data[4]
#define tDecorWidth data[5]
#define tDecorHeight data[6]
#define tButton data[10]
#define tDecorationMenuCommand data[11]
#define tDecorationItemsMenuCommand data[12]
#define tMenuTaskId data[13]
#define DECOR_MENU_PLACE 0
#define DECOR_MENU_TOSS 1
#define DECOR_MENU_TRADE 2
#define DECOR_ITEMS_MENU_PLACE 0
#define DECOR_ITEMS_MENU_PUT_AWAY 1
struct DecorationItemsMenu
{
struct ListMenuItem items[41];
u8 names[41][24];
u8 numMenuItems;
u8 maxShownItems;
u8 scrollIndicatorsTaskId;
};
struct PlaceDecorationGraphicsDataBuffer
{
const struct Decoration *decoration;
u16 tiles[0x40];
u8 image[0x800];
u16 palette[16];
};
struct DecorRearrangementDataBuffer
{
u8 idx;
u8 width;
u8 height;
u16 flagId;
};
struct DecorationPCContext
{
u8 *items;
u8 *pos;
u8 size;
u8 isPlayerRoom;
};
enum Windows
{
WINDOW_MAIN_MENU,
WINDOW_DECORATION_CATEGORIES,
WINDOW_DECORATION_CATEGORY_SUMMARY,
WINDOW_DECORATION_CATEGORY_ITEMS,
WINDOW_COUNT
};
EWRAM_DATA u8 *gCurDecorationItems = NULL;
EWRAM_DATA static u8 sDecorationActionsCursorPos = 0;
EWRAM_DATA static u8 sNumOwnedDecorationsInCurCategory = 0;
EWRAM_DATA static u8 sSecretBaseItemsIndicesBuffer[DECOR_MAX_SECRET_BASE] = {};
EWRAM_DATA static u8 sPlayerRoomItemsIndicesBuffer[DECOR_MAX_PLAYERS_HOUSE] = {};
EWRAM_DATA static u16 sDecorationsCursorPos = 0;
EWRAM_DATA static u16 sDecorationsScrollOffset = 0;
EWRAM_DATA u8 gCurDecorationIndex = 0;
EWRAM_DATA static u8 sCurDecorationCategory = DECORCAT_DESK;
EWRAM_DATA static u32 filler_0203a174[2] = {};
EWRAM_DATA static struct DecorationPCContext sDecorationContext = {};
EWRAM_DATA static u8 sDecorMenuWindowIds[WINDOW_COUNT] = {};
EWRAM_DATA static struct DecorationItemsMenu *sDecorationItemsMenu = NULL;
EWRAM_DATA static struct PlaceDecorationGraphicsDataBuffer sPlaceDecorationGraphicsDataBuffer = {};
EWRAM_DATA static u16 sCurDecorMapX = 0;
EWRAM_DATA static u16 sCurDecorMapY = 0;
EWRAM_DATA static u8 sDecor_CameraSpriteObjectIdx1 = 0;
EWRAM_DATA static u8 sDecor_CameraSpriteObjectIdx2 = 0;
EWRAM_DATA static u8 sDecorationLastDirectionMoved = 0;
EWRAM_DATA static struct OamData sDecorSelectorOam = {};
EWRAM_DATA static struct DecorRearrangementDataBuffer sDecorRearrangementDataBuffer[DECOR_MAX_SECRET_BASE] = {};
EWRAM_DATA static u8 sCurDecorSelectedInRearrangement = 0;
static void HandleDecorationActionsMenuInput(u8 taskId);
static void PrintCurMainMenuDescription(void);
static void DecorationMenuAction_Decorate(u8 taskId);
static void DecorationMenuAction_PutAway(u8 taskId);
static void DecorationMenuAction_Toss(u8 taskId);
static void DecorationMenuAction_Cancel(u8 taskId);
static void ReturnToDecorationActionsAfterInvalidSelection(u8 taskId);
static void SecretBasePC_PrepMenuForSelectingStoredDecors(u8 taskId);
static void InitDecorationCategoriesWindow(u8 taskId);
static void PrintDecorationCategoryMenuItems(u8 taskId);
static void PrintDecorationCategoryMenuItem(u8 winid, u8 category, u8 x, u8 y, bool8 disabled, u8 speed);
static void ColorMenuItemString(u8 *str, bool8 disabled);
static void HandleDecorationCategoriesMenuInput(u8 taskId);
static void SelectDecorationCategory(u8 taskId);
static void ReturnToDecorationCategoriesAfterInvalidSelection(u8 taskId);
static void ExitDecorationCategoriesMenu(u8 taskId);
static void ReturnToActionsMenuFromCategories(u8 taskId);
static void ExitTraderDecorationMenu(u8 taskId);
static void CopyDecorationMenuItemName(u8 *dest, u16 decoration);
static void DecorationItemsMenu_OnCursorMove(s32 itemIndex, bool8 flag, struct ListMenu *menu);
static void DecorationItemsMenu_PrintDecorationInUse(u8 windowId, s32 itemIndex, u8 y);
static void ShowDecorationItemsWindow(u8 taskId);
static void HandleDecorationItemsMenuInput(u8 taskId);
static void PrintDecorationItemDescription(s32 itemIndex);
static void RemoveDecorationItemsOtherWindows(void);
static bool8 IsDecorationIndexInSecretBase(u8 idx);
static bool8 IsDecorationIndexInPlayersRoom(u8 idx);
static void IdentifyOwnedDecorationsCurrentlyInUse(u8 taskId);
static void InitDecorationItemsWindow(u8 taskId);
static void ShowDecorationCategorySummaryWindow(u8 category);
static void DontTossDecoration(u8 taskId);
static void DecorationItemsMenuAction_Cancel(u8 taskId);
static void DecorationItemsMenuAction_AttemptPlace(u8 taskId);
static void Task_PlaceDecoration(u8 taskId);
static void ConfigureCameraObjectForPlacingDecoration(struct PlaceDecorationGraphicsDataBuffer *data, u8 decor);
static void SetUpPlacingDecorationPlayerAvatar(u8 taskId, struct PlaceDecorationGraphicsDataBuffer *data);
static void SetUpDecorationShape(u8 taskId);
static void AttemptPlaceDecoration(u8 taskId);
static void AttemptCancelPlaceDecoration(u8 taskId);
static void AttemptPlaceDecoration_(u8 taskId);
static void PlaceDecorationPrompt(u8 taskId);
static void PlaceDecoration(u8 taskId);
static void PlaceDecoration_(u8 taskId);
static void CancelDecoratingPrompt(u8 taskId);
static void CancelDecorating(u8 taskId);
static void CancelDecorating_(u8 taskId);
static void c1_overworld_prev_quest(u8 taskId);
static void FieldCB_InitDecorationItemsWindow(void);
static void ResetCursorMovement(void);
static void ContinueDecorating(u8 taskId);
static void CantPlaceDecorationPrompt(u8 taskId);
static void InitializePuttingAwayCursorSprite(struct Sprite *sprite);
static void InitializePuttingAwayCursorSprite2(struct Sprite *sprite);
static u8 gpu_pal_decompress_alloc_tag_and_upload(struct PlaceDecorationGraphicsDataBuffer *data, u8 decor);
static const u32 *GetDecorationIconPicOrPalette(u16 decor, u8 mode);
static bool8 HasDecorationsInUse(u8 taskId);
static void Task_ContinuePuttingAwayDecorations(u8 taskId);
static void ContinuePuttingAwayDecorations(u8 taskId);
static void AttemptPutAwayDecoration(u8 taskId);
static void AttemptCancelPutAwayDecoration(u8 taskId);
static void AttemptPutAwayDecoration_(u8 taskId);
static void ContinuePuttingAwayDecorationsPrompt(u8 taskId);
static void AttemptMarkDecorUnderCursorForRemoval(u8 taskId);
static void ReturnDecorationPrompt(u8 taskId);
static void PutAwayDecoration(u8 taskId);
static void StopPuttingAwayDecorationsPrompt(u8 taskId);
static void StopPuttingAwayDecorations(u8 taskId);
static void StopPuttingAwayDecorations_(u8 taskId);
static void Task_StopPuttingAwayDecorations(u8 taskId);
static void FieldCB_StopPuttingAwayDecorations(void);
static void InitializeCameraSprite1(struct Sprite *sprite);
static void LoadPlayerSpritePalette(void);
static void FreePlayerSpritePalette(void);
static void DecorationItemsMenuAction_AttemptToss(u8 taskId);
static void TossDecorationPrompt(u8 taskId);
static void TossDecoration(u8 taskId);
#include "data/decoration/tiles.h"
#include "data/decoration/description.h"
#include "data/decoration/header.h"
static const u8 *const sDecorationCategoryNames[] =
{
gText_Desk,
gText_Chair,
gText_Plant,
gText_Ornament,
gText_Mat,
gText_Poster,
gText_Doll,
gText_Cushion
};
static const struct MenuAction sDecorationMainMenuActions[] =
{
{
.text = gText_Decorate,
.func = { .void_u8 = DecorationMenuAction_Decorate },
},
{
.text = gText_PutAway,
.func = { .void_u8 = DecorationMenuAction_PutAway },
},
{
.text = gText_Toss2,
.func = { .void_u8 = DecorationMenuAction_Toss },
},
{
.text = gText_Cancel,
.func = { .void_u8 = DecorationMenuAction_Cancel },
},
};
static const u8 *const sSecretBasePCMenuItemDescriptions[] =
{
gText_PutOutSelectedDecorItem,
gText_StoreChosenDecorInPC,
gText_ThrowAwayUnwantedDecors,
gText_GoBackPrevMenu
};
static const TaskFunc sSecretBasePC_SelectedDecorationActions[][2] =
{
{ DecorationItemsMenuAction_AttemptPlace, DecorationItemsMenuAction_Cancel },
{ DecorationItemsMenuAction_AttemptToss, DecorationItemsMenuAction_Cancel },
{ DecorationItemsMenuAction_Trade, DecorationItemsMenuAction_Cancel },
};
static const struct WindowTemplate sDecorationWindowTemplates[WINDOW_COUNT] =
{
{
.bg = 0,
.tilemapLeft = 1,
.tilemapTop = 1,
.width = 18,
.height = 2 * ARRAY_COUNT(sDecorationMainMenuActions),
.paletteNum = 15,
.baseBlock = 0x0001
},
{
.bg = 0,
.tilemapLeft = 1,
.tilemapTop = 1,
.width = 13,
.height = 18,
.paletteNum = 13,
.baseBlock = 0x0091
},
{
.bg = 0,
.tilemapLeft = 17,
.tilemapTop = 1,
.width = 12,
.height = 2,
.paletteNum = 15,
.baseBlock = 0x017b
},
{
.bg = 0,
.tilemapLeft = 16,
.tilemapTop = 13,
.width = 13,
.height = 6,
.paletteNum = 15,
.baseBlock = 0x0193
}
};
static const u16 sDecorationMenuPalette[] = INCBIN_U16("graphics/decorations/decoration_menu.gbapal");
static const struct ListMenuTemplate sDecorationItemsListMenuTemplate =
{
.items = NULL,
.moveCursorFunc = DecorationItemsMenu_OnCursorMove,
.itemPrintFunc = DecorationItemsMenu_PrintDecorationInUse,
.totalItems = 0,
.maxShowed = 0,
.windowId = 0,
.header_X = 0,
.item_X = 8,
.cursor_X = 0,
.upText_Y = 9,
.cursorPal = 2,
.fillValue = 1,
.cursorShadowPal = 3,
.lettersSpacing = FALSE,
.itemVerticalPadding = 0,
.scrollMultiple = FALSE,
.fontId = 7
};
#include "data/decoration/icon.h"
#include "data/decoration/tilemaps.h"
static const struct {
u8 shape;
u8 size;
u8 cameraX;
u8 cameraY;
} sDecorationMovementInfo[] =
{
[DECORSHAPE_1x1] = {SPRITE_SHAPE(16x16), SPRITE_SIZE(16x16), 120, 78},
[DECORSHAPE_2x1] = {SPRITE_SHAPE(32x16), SPRITE_SIZE(32x16), 128, 78},
[DECORSHAPE_3x1] = {SPRITE_SHAPE(64x32), SPRITE_SIZE(64x32), 144, 86},
[DECORSHAPE_4x2] = {SPRITE_SHAPE(64x32), SPRITE_SIZE(64x32), 144, 70},
[DECORSHAPE_2x2] = {SPRITE_SHAPE(32x32), SPRITE_SIZE(32x32), 128, 70},
[DECORSHAPE_1x2] = {SPRITE_SHAPE(16x32), SPRITE_SIZE(16x32), 120, 70},
[DECORSHAPE_1x3] = {SPRITE_SHAPE(32x64), SPRITE_SIZE(32x64), 128, 86},
[DECORSHAPE_2x4] = {SPRITE_SHAPE(32x64), SPRITE_SIZE(32x64), 128, 54},
[DECORSHAPE_3x3] = {SPRITE_SHAPE(64x64), SPRITE_SIZE(64x64), 144, 70},
[DECORSHAPE_3x2] = {SPRITE_SHAPE(64x32), SPRITE_SIZE(64x32), 144, 70},
};
static const union AnimCmd sDecorSelectorAnimCmd0[] =
{
ANIMCMD_FRAME(0, 0, FALSE, FALSE),
ANIMCMD_END
};
static const union AnimCmd *const sDecorSelectorAnimCmds[] = { sDecorSelectorAnimCmd0 };
static const struct SpriteFrameImage sDecorSelectorSpriteFrameImages =
{
.data = (const u8 *)&sPlaceDecorationGraphicsDataBuffer.image,
.size = 0x800,
};
static const struct SpriteTemplate sDecorationSelectorSpriteTemplate =
{
0xFFFF,
PLACE_DECORATION_SELECTOR_TAG,
&sDecorSelectorOam,
sDecorSelectorAnimCmds,
&sDecorSelectorSpriteFrameImages,
gDummySpriteAffineAnimTable,
SpriteCallbackDummy
};
static const struct SpriteTemplate sDecorWhilePlacingSpriteTemplate =
{
0x0000,
0x0000,
&sDecorSelectorOam,
sDecorSelectorAnimCmds,
NULL,
gDummySpriteAffineAnimTable,
SpriteCallbackDummy
};
static const struct SpritePalette sSpritePal_PlaceDecoration =
{
.data = (const u16 *)&sPlaceDecorationGraphicsDataBuffer.palette,
.tag = PLACE_DECORATION_SELECTOR_TAG,
};
static const struct YesNoFuncTable sPlaceDecorationYesNoFunctions =
{
.yesFunc = PlaceDecoration,
.noFunc = ContinueDecorating,
};
static const struct YesNoFuncTable sCancelDecoratingYesNoFunctions =
{
.yesFunc = CancelDecorating,
.noFunc = ContinueDecorating,
};
static const struct YesNoFuncTable sPlacePutAwayYesNoFunctions[] =
{
{
.yesFunc = AttemptPlaceDecoration,
.noFunc = AttemptCancelPlaceDecoration,
},
{
.yesFunc = AttemptPutAwayDecoration,
.noFunc = AttemptCancelPutAwayDecoration,
}
};
static const u8 sDecorationStandElevations[] =
{
4, 4, 4, 4,
0, 3, 3, 0
};
static const u8 sDecorationSlideElevation[] =
{
4, 4,
4, 4,
0, 4,
3, 0,
};
static const u16 sDecorShapeSizes[] = {
0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x10, 0x20, 0x40, 0x20
};
static const u16 sBrendanPalette[] = INCBIN_U16("graphics/decorations/brendan.gbapal");
static const u16 sMayPalette[] = INCBIN_U16("graphics/decorations/may.gbapal");
static const struct YesNoFuncTable sReturnDecorationYesNoFunctions =
{
.yesFunc = PutAwayDecoration,
.noFunc = ContinuePuttingAwayDecorations,
};
static const struct YesNoFuncTable sStopPuttingAwayDecorationsYesNoFunctions =
{
.yesFunc = StopPuttingAwayDecorations,
.noFunc = ContinuePuttingAwayDecorations,
};
static const u8 sDecorationPuttingAwayCursor[] = INCBIN_U8("graphics/misc/decoration_putting_away_cursor.4bpp");
static const struct SpritePalette sSpritePal_PuttingAwayCursorBrendan =
{
.data = sBrendanPalette,
.tag = PLACE_DECORATION_PLAYER_TAG,
};
static const struct SpritePalette sSpritePal_PuttingAwayCursorMay =
{
.data = sMayPalette,
.tag = PLACE_DECORATION_PLAYER_TAG,
};
static const struct OamData sPuttingAwayCursorOamData =
{
.y = 0,
.affineMode = ST_OAM_AFFINE_OFF,
.objMode = ST_OAM_OBJ_NORMAL,
.bpp = ST_OAM_4BPP,
.shape = SPRITE_SHAPE(16x16),
.x = 0,
.size = SPRITE_SIZE(16x16),
.tileNum = 0,
.priority = 1,
.paletteNum = 0,
};
static const union AnimCmd sPuttingAwayCursorAnimCmd0[] =
{
ANIMCMD_FRAME(0, 0, 0),
ANIMCMD_END
};
static const union AnimCmd *const sPuttingAwayCursorAnimCmds[] =
{
sPuttingAwayCursorAnimCmd0,
};
static const struct SpriteFrameImage sPuttingAwayCursorPicTable =
{
.data = sDecorationPuttingAwayCursor,
.size = sizeof(sDecorationPuttingAwayCursor),
};
static const struct SpriteTemplate sPuttingAwayCursorSpriteTemplate =
{
0xFFFF,
PLACE_DECORATION_PLAYER_TAG,
&sPuttingAwayCursorOamData,
sPuttingAwayCursorAnimCmds,
&sPuttingAwayCursorPicTable,
gDummySpriteAffineAnimTable,
InitializeCameraSprite1
};
static const struct YesNoFuncTable sTossDecorationYesNoFunctions =
{
.yesFunc = TossDecoration,
.noFunc = DontTossDecoration,
};
void InitDecorationContextItems(void)
{
if (sCurDecorationCategory < DECORCAT_COUNT)
gCurDecorationItems = gDecorationInventories[sCurDecorationCategory].items;
if (sDecorationContext.isPlayerRoom == FALSE)
{
sDecorationContext.items = gSaveBlock1Ptr->secretBases[0].decorations;
sDecorationContext.pos = gSaveBlock1Ptr->secretBases[0].decorationPositions;
}
if (sDecorationContext.isPlayerRoom == TRUE)
{
sDecorationContext.items = gSaveBlock1Ptr->playerRoomDecorations;
sDecorationContext.pos = gSaveBlock1Ptr->playerRoomDecorationPositions;
}
}
static u8 AddDecorationWindow(u8 windowIndex)
{
u8 *windowId;
struct WindowTemplate template;
windowId = &sDecorMenuWindowIds[windowIndex];
if (windowIndex == WINDOW_MAIN_MENU)
{
template = sDecorationWindowTemplates[WINDOW_MAIN_MENU];
template.width = GetMaxWidthInMenuTable(sDecorationMainMenuActions, ARRAY_COUNT(sDecorationMainMenuActions));
if (template.width > 18)
template.width = 18;
*windowId = AddWindow(&template);
}
else
{
*windowId = AddWindow(&sDecorationWindowTemplates[windowIndex]);
}
DrawStdFrameWithCustomTileAndPalette(*windowId, FALSE, 0x214, 14);
ScheduleBgCopyTilemapToVram(0);
return *windowId;
}
static void RemoveDecorationWindow(u8 windowIndex)
{
ClearStdWindowAndFrameToTransparent(sDecorMenuWindowIds[windowIndex], FALSE);
ClearWindowTilemap(sDecorMenuWindowIds[windowIndex]);
RemoveWindow(sDecorMenuWindowIds[windowIndex]);
ScheduleBgCopyTilemapToVram(0);
}
static void AddDecorationActionsWindow(void)
{
u8 windowId = AddDecorationWindow(WINDOW_MAIN_MENU);
PrintMenuTable(windowId, ARRAY_COUNT(sDecorationMainMenuActions), sDecorationMainMenuActions);
InitMenuInUpperLeftCornerPlaySoundWhenAPressed(windowId, ARRAY_COUNT(sDecorationMainMenuActions), sDecorationActionsCursorPos);
}
static void InitDecorationActionsWindow(void)
{
sDecorationActionsCursorPos = 0;
ScriptContext2_Enable();
AddDecorationActionsWindow();
PrintCurMainMenuDescription();
}
void DoSecretBaseDecorationMenu(u8 taskId)
{
InitDecorationActionsWindow();
sDecorationContext.items = gSaveBlock1Ptr->secretBases[0].decorations;
sDecorationContext.pos = gSaveBlock1Ptr->secretBases[0].decorationPositions;
sDecorationContext.size = DECOR_MAX_SECRET_BASE;
sDecorationContext.isPlayerRoom = FALSE;
gTasks[taskId].func = HandleDecorationActionsMenuInput;
}
void DoPlayerRoomDecorationMenu(u8 taskId)
{
InitDecorationActionsWindow();
sDecorationContext.items = gSaveBlock1Ptr->playerRoomDecorations;
sDecorationContext.pos = gSaveBlock1Ptr->playerRoomDecorationPositions;
sDecorationContext.size = DECOR_MAX_PLAYERS_HOUSE;
sDecorationContext.isPlayerRoom = TRUE;
gTasks[taskId].func = HandleDecorationActionsMenuInput;
}
static void HandleDecorationActionsMenuInput(u8 taskId)
{
if (!gPaletteFade.active)
{
s8 menuPos = Menu_GetCursorPos();
switch (Menu_ProcessInput())
{
default:
PlaySE(SE_SELECT);
sDecorationMainMenuActions[sDecorationActionsCursorPos].func.void_u8(taskId);
break;
case MENU_NOTHING_CHOSEN:
sDecorationActionsCursorPos = Menu_GetCursorPos();
if (menuPos != sDecorationActionsCursorPos)
PrintCurMainMenuDescription();
break;
case MENU_B_PRESSED:
PlaySE(SE_SELECT);
DecorationMenuAction_Cancel(taskId);
break;
}
}
}
static void PrintCurMainMenuDescription(void)
{
FillWindowPixelBuffer(0, PIXEL_FILL(1));
AddTextPrinterParameterized2(0, 1, sSecretBasePCMenuItemDescriptions[sDecorationActionsCursorPos], 0, 0, 2, 1, 3);
}
static void DecorationMenuAction_Decorate(u8 taskId)
{
if (GetNumOwnedDecorations() == 0)
{
StringExpandPlaceholders(gStringVar4, gText_NoDecorations);
DisplayItemMessageOnField(taskId, gStringVar4, ReturnToDecorationActionsAfterInvalidSelection);
}
else
{
gTasks[taskId].tDecorationMenuCommand = DECOR_MENU_PLACE;
sCurDecorationCategory = DECORCAT_DESK;
SecretBasePC_PrepMenuForSelectingStoredDecors(taskId);
}
}
static void DecorationMenuAction_PutAway(u8 taskId)
{
if (!HasDecorationsInUse(taskId))
{
StringExpandPlaceholders(gStringVar4, gText_NoDecorationsInUse);
DisplayItemMessageOnField(taskId, gStringVar4, ReturnToDecorationActionsAfterInvalidSelection);
}
else
{
RemoveDecorationWindow(WINDOW_MAIN_MENU);
ClearDialogWindowAndFrame(0, 0);
FadeScreen(FADE_TO_BLACK, 0);
gTasks[taskId].tState = 0;
gTasks[taskId].func = Task_ContinuePuttingAwayDecorations;
}
}
static void DecorationMenuAction_Toss(u8 taskId)
{
if (GetNumOwnedDecorations() == 0)
{
StringExpandPlaceholders(gStringVar4, gText_NoDecorations);
DisplayItemMessageOnField(taskId, gStringVar4, ReturnToDecorationActionsAfterInvalidSelection);
}
else
{
gTasks[taskId].tDecorationMenuCommand = DECOR_MENU_TOSS;
sCurDecorationCategory = DECORCAT_DESK;
SecretBasePC_PrepMenuForSelectingStoredDecors(taskId);
}
}
static void DecorationMenuAction_Cancel(u8 taskId)
{
RemoveDecorationWindow(WINDOW_MAIN_MENU);
if (!sDecorationContext.isPlayerRoom)
{
ScriptContext1_SetupScript(SecretBase_EventScript_PCCancel);
DestroyTask(taskId);
}
else
{
ReshowPlayerPC(taskId);
}
}
static void ReturnToDecorationActionsAfterInvalidSelection(u8 taskId)
{
PrintCurMainMenuDescription();
gTasks[taskId].func = HandleDecorationActionsMenuInput;
}
static void SecretBasePC_PrepMenuForSelectingStoredDecors(u8 taskId)
{
LoadPalette(sDecorationMenuPalette, 0xd0, 0x20);
ClearDialogWindowAndFrame(0, 0);
RemoveDecorationWindow(WINDOW_MAIN_MENU);
InitDecorationCategoriesWindow(taskId);
}
static void InitDecorationCategoriesWindow(u8 taskId)
{
u8 windowId = AddDecorationWindow(WINDOW_DECORATION_CATEGORIES);
PrintDecorationCategoryMenuItems(taskId);
InitMenuInUpperLeftCornerPlaySoundWhenAPressed(windowId, DECORCAT_COUNT + 1, sCurDecorationCategory);
gTasks[taskId].func = HandleDecorationCategoriesMenuInput;
}
static void ReinitDecorationCategoriesWindow(u8 taskId)
{
FillWindowPixelBuffer(sDecorMenuWindowIds[WINDOW_DECORATION_CATEGORIES], PIXEL_FILL(1));
PrintDecorationCategoryMenuItems(taskId);
InitMenuInUpperLeftCornerPlaySoundWhenAPressed(sDecorMenuWindowIds[WINDOW_DECORATION_CATEGORIES], DECORCAT_COUNT + 1, sCurDecorationCategory);
gTasks[taskId].func = HandleDecorationCategoriesMenuInput;
}
static void PrintDecorationCategoryMenuItems(u8 taskId)
{
u8 i;
s16 *data = gTasks[taskId].data;
u8 windowId = sDecorMenuWindowIds[WINDOW_DECORATION_CATEGORIES];
bool8 isPlayerRoom = sDecorationContext.isPlayerRoom;
bool8 shouldDisable = FALSE;
if (isPlayerRoom == TRUE && tDecorationMenuCommand == DECOR_MENU_PLACE)
shouldDisable = TRUE;
for (i = 0; i < DECORCAT_COUNT; i++)
{
// Only DOLL and CUSHION decorations are enabled when decorating the player's room.
if (shouldDisable == TRUE && i != DECORCAT_DOLL && i != DECORCAT_CUSHION)
PrintDecorationCategoryMenuItem(windowId, i, 8, i * 16, TRUE, TEXT_SPEED_FF);
else
PrintDecorationCategoryMenuItem(windowId, i, 8, i * 16, FALSE, TEXT_SPEED_FF);
}
AddTextPrinterParameterized(windowId, 1, gTasks[taskId].tDecorationMenuCommand == DECOR_MENU_TRADE ? gText_Exit : gText_Cancel, 8, i * 16 + 1, 0, NULL);
ScheduleBgCopyTilemapToVram(0);
}
static void PrintDecorationCategoryMenuItem(u8 winid, u8 category, u8 x, u8 y, bool8 disabled, u8 speed)
{
u8 width;
u8 *str;
width = x == 8 ? 104 : 96;
y++;
ColorMenuItemString(gStringVar4, disabled);
str = StringLength(gStringVar4) + gStringVar4;
StringCopy(str, sDecorationCategoryNames[category]);
AddTextPrinterParameterized(winid, 1, gStringVar4, x, y, speed, NULL);
str = ConvertIntToDecimalStringN(str, GetNumOwnedDecorationsInCategory(category), STR_CONV_MODE_RIGHT_ALIGN, 2);
*(str++) = CHAR_SLASH;
ConvertIntToDecimalStringN(str, gDecorationInventories[category].size, STR_CONV_MODE_RIGHT_ALIGN, 2);
x = GetStringRightAlignXOffset(1, gStringVar4, width);
AddTextPrinterParameterized(winid, 1, gStringVar4, x, y, speed, NULL);
}
static void ColorMenuItemString(u8 *str, bool8 disabled)
{
StringCopy(str, gText_Color161Shadow161);
if (disabled == TRUE)
{
str[2] = 4;
str[5] = 5;
}
else
{
str[2] = 2;
str[5] = 3;
}
}
static void HandleDecorationCategoriesMenuInput(u8 taskId)
{
if (!gPaletteFade.active)
{
s8 input = Menu_ProcessInput();
switch (input)
{
case MENU_B_PRESSED:
case DECORCAT_COUNT: // CANCEL
PlaySE(SE_SELECT);
ExitDecorationCategoriesMenu(taskId);
break;
case MENU_NOTHING_CHOSEN:
break;
default:
PlaySE(SE_SELECT);
sCurDecorationCategory = input;
SelectDecorationCategory(taskId);
break;
}
}
}
static void SelectDecorationCategory(u8 taskId)
{
sNumOwnedDecorationsInCurCategory = GetNumOwnedDecorationsInCategory(sCurDecorationCategory);
if (sNumOwnedDecorationsInCurCategory != 0)
{
CondenseDecorationsInCategory(sCurDecorationCategory);
gCurDecorationItems = gDecorationInventories[sCurDecorationCategory].items;
IdentifyOwnedDecorationsCurrentlyInUse(taskId);
sDecorationsScrollOffset = 0;
sDecorationsCursorPos = 0;
gTasks[taskId].func = ShowDecorationItemsWindow;
}
else
{
RemoveDecorationWindow(WINDOW_DECORATION_CATEGORIES);
StringExpandPlaceholders(gStringVar4, gText_NoDecorations);
DisplayItemMessageOnField(taskId, gStringVar4, ReturnToDecorationCategoriesAfterInvalidSelection);
}
}
static void ReturnToDecorationCategoriesAfterInvalidSelection(u8 taskId)
{
ClearDialogWindowAndFrame(0, 0);
InitDecorationCategoriesWindow(taskId);
}
static void ExitDecorationCategoriesMenu(u8 taskId)
{
if (gTasks[taskId].tDecorationMenuCommand != DECOR_MENU_TRADE)
ReturnToActionsMenuFromCategories(taskId);
else
ExitTraderDecorationMenu(taskId);
}
static void ReturnToActionsMenuFromCategories(u8 taskId)
{
RemoveDecorationWindow(WINDOW_DECORATION_CATEGORIES);
AddDecorationActionsWindow();
DrawDialogueFrame(0, 0);
PrintCurMainMenuDescription();
gTasks[taskId].func = HandleDecorationActionsMenuInput;
}
void ShowDecorationCategoriesWindow(u8 taskId)
{
LoadPalette(sDecorationMenuPalette, 0xd0, 0x20);
ClearDialogWindowAndFrame(0, 0);
gTasks[taskId].tDecorationMenuCommand = DECOR_MENU_TRADE;
sCurDecorationCategory = DECORCAT_DESK;
InitDecorationCategoriesWindow(taskId);
}
void CopyDecorationCategoryName(u8 *dest, u8 category)
{
StringCopy(dest, sDecorationCategoryNames[category]);
}
static void ExitTraderDecorationMenu(u8 taskId)
{
RemoveDecorationWindow(WINDOW_DECORATION_CATEGORIES);
ExitTraderMenu(taskId);
}
static void InitDecorationItemsMenuLimits(void)
{
sDecorationItemsMenu->numMenuItems = sNumOwnedDecorationsInCurCategory + 1;
if (sDecorationItemsMenu->numMenuItems > 8)
sDecorationItemsMenu->maxShownItems = 8;
else
sDecorationItemsMenu->maxShownItems = sDecorationItemsMenu->numMenuItems;
}
static void InitDecorationItemsMenuScrollAndCursor(void)
{
sub_812225C(&sDecorationsScrollOffset, &sDecorationsCursorPos, sDecorationItemsMenu->maxShownItems, sDecorationItemsMenu->numMenuItems);
}
static void InitDecorationItemsMenuScrollAndCursor2(void)
{
sub_8122298(&sDecorationsScrollOffset, &sDecorationsCursorPos, sDecorationItemsMenu->maxShownItems, sDecorationItemsMenu->numMenuItems, 8);
}
static void PrintDecorationItemMenuItems(u8 taskId)
{
s16 *data;
u16 i;
data = gTasks[taskId].data;
if ((sCurDecorationCategory < DECORCAT_DOLL || sCurDecorationCategory > DECORCAT_CUSHION) && sDecorationContext.isPlayerRoom == TRUE && tDecorationMenuCommand == DECOR_MENU_PLACE)
ColorMenuItemString(gStringVar1, TRUE);
else
ColorMenuItemString(gStringVar1, FALSE);
for (i = 0; i < sDecorationItemsMenu->numMenuItems - 1; i++)
{
CopyDecorationMenuItemName(sDecorationItemsMenu->names[i], gCurDecorationItems[i]);
sDecorationItemsMenu->items[i].name = sDecorationItemsMenu->names[i];
sDecorationItemsMenu->items[i].id = i;
}
StringCopy(sDecorationItemsMenu->names[i], gText_Cancel);
sDecorationItemsMenu->items[i].name = sDecorationItemsMenu->names[i];
sDecorationItemsMenu->items[i].id = -2;
gMultiuseListMenuTemplate = sDecorationItemsListMenuTemplate;
gMultiuseListMenuTemplate.windowId = sDecorMenuWindowIds[WINDOW_DECORATION_CATEGORIES];
gMultiuseListMenuTemplate.totalItems = sDecorationItemsMenu->numMenuItems;
gMultiuseListMenuTemplate.items = sDecorationItemsMenu->items;
gMultiuseListMenuTemplate.maxShowed = sDecorationItemsMenu->maxShownItems;
}
static void CopyDecorationMenuItemName(u8 *dest, u16 decoration)
{
StringCopy(dest, gStringVar1);
StringAppend(dest, gDecorations[decoration].name);
}
static void DecorationItemsMenu_OnCursorMove(s32 itemIndex, bool8 flag, struct ListMenu *menu)
{
if (flag != TRUE)
PlaySE(SE_SELECT);
PrintDecorationItemDescription(itemIndex);
}
static void DecorationItemsMenu_PrintDecorationInUse(u8 windowId, s32 itemIndex, u8 y)
{
if (itemIndex != -2)
{
if (IsDecorationIndexInSecretBase(itemIndex + 1) == TRUE)
blit_move_info_icon(windowId, 0x18, 0x5c, y + 2);
else if (IsDecorationIndexInPlayersRoom(itemIndex + 1) == TRUE)
blit_move_info_icon(windowId, 0x19, 0x5c, y + 2);
}
}
static void AddDecorationItemsScrollIndicators(void)
{
if (sDecorationItemsMenu->scrollIndicatorsTaskId == 0xFF)
{
sDecorationItemsMenu->scrollIndicatorsTaskId = AddScrollIndicatorArrowPairParameterized(
SCROLL_ARROW_UP,
0x3c,
0x0c,
0x94,
sDecorationItemsMenu->numMenuItems - sDecorationItemsMenu->maxShownItems,
0x6e,
0x6e,
&sDecorationsScrollOffset);
}
}
static void RemoveDecorationItemsScrollIndicators(void)
{
if (sDecorationItemsMenu->scrollIndicatorsTaskId != 0xFF)
{
RemoveScrollIndicatorArrowPair(sDecorationItemsMenu->scrollIndicatorsTaskId);
sDecorationItemsMenu->scrollIndicatorsTaskId = 0xFF;
}
}
static void AddDecorationItemsWindow(u8 taskId)
{
AddDecorationWindow(WINDOW_DECORATION_CATEGORIES);
InitDecorationItemsWindow(taskId);
}
static void InitDecorationItemsWindow(u8 taskId)
{
s16 *data = gTasks[taskId].data;
AddDecorationWindow(WINDOW_DECORATION_CATEGORY_ITEMS);
ShowDecorationCategorySummaryWindow(sCurDecorationCategory);
sDecorationItemsMenu = AllocZeroed(sizeof(*sDecorationItemsMenu));
sDecorationItemsMenu->scrollIndicatorsTaskId = 0xFF;
InitDecorationItemsMenuLimits();
InitDecorationItemsMenuScrollAndCursor();
InitDecorationItemsMenuScrollAndCursor2();
PrintDecorationItemMenuItems(taskId);
tMenuTaskId = ListMenuInit(&gMultiuseListMenuTemplate, sDecorationsScrollOffset, sDecorationsCursorPos);
AddDecorationItemsScrollIndicators();
}
static void ShowDecorationItemsWindow(u8 taskId)
{
InitDecorationItemsWindow(taskId);
gTasks[taskId].func = HandleDecorationItemsMenuInput;
}
static void HandleDecorationItemsMenuInput(u8 taskId)
{
s16 *data;
s32 input;
data = gTasks[taskId].data;
if (!gPaletteFade.active)
{
input = ListMenu_ProcessInput(tMenuTaskId);
ListMenuGetScrollAndRow(tMenuTaskId, &sDecorationsScrollOffset, &sDecorationsCursorPos);
switch (input)
{
case LIST_NOTHING_CHOSEN:
break;
case LIST_CANCEL:
PlaySE(SE_SELECT);
sSecretBasePC_SelectedDecorationActions[tDecorationMenuCommand][1](taskId);
break;
default:
PlaySE(SE_SELECT);
gCurDecorationIndex = input;
RemoveDecorationItemsScrollIndicators();
DestroyListMenuTask(tMenuTaskId, &sDecorationsScrollOffset, &sDecorationsCursorPos);
RemoveDecorationWindow(WINDOW_DECORATION_CATEGORIES);
RemoveDecorationItemsOtherWindows();
free(sDecorationItemsMenu);
sSecretBasePC_SelectedDecorationActions[tDecorationMenuCommand][0](taskId);
break;
}
}
}
static void ShowDecorationCategorySummaryWindow(u8 category)
{
PrintDecorationCategoryMenuItem(AddDecorationWindow(WINDOW_DECORATION_CATEGORY_SUMMARY), category, 0, 0, 0, 0);
}
static void PrintDecorationItemDescription(s32 itemIndex)
{
u8 windowId;
const u8 *str;
windowId = sDecorMenuWindowIds[WINDOW_DECORATION_CATEGORY_ITEMS];
FillWindowPixelBuffer(windowId, PIXEL_FILL(1));
if ((u32)itemIndex >= sNumOwnedDecorationsInCurCategory)
str = gText_GoBackPrevMenu;
else
str = gDecorations[gCurDecorationItems[itemIndex]].description;
AddTextPrinterParameterized(windowId, 1, str, 0, 1, 0, 0);
}
static void RemoveDecorationItemsOtherWindows(void)
{
RemoveDecorationWindow(WINDOW_DECORATION_CATEGORY_ITEMS);
RemoveDecorationWindow(WINDOW_DECORATION_CATEGORY_SUMMARY);
}
static bool8 IsDecorationIndexInSecretBase(u8 idx)
{
u8 i;
for (i = 0; i < ARRAY_COUNT(sSecretBaseItemsIndicesBuffer); i++)
{
if (sSecretBaseItemsIndicesBuffer[i] == idx)
return TRUE;
}
return FALSE;
}
static bool8 IsDecorationIndexInPlayersRoom(u8 idx)
{
u8 i;
for (i = 0; i < ARRAY_COUNT(sPlayerRoomItemsIndicesBuffer); i++)
{
if (sPlayerRoomItemsIndicesBuffer[i] == idx)
return TRUE;
}
return FALSE;
}
static void IdentifyOwnedDecorationsCurrentlyInUseInternal(u8 taskId)
{
u16 i, j, k;
u16 count;
count = 0;
memset(sSecretBaseItemsIndicesBuffer, 0, sizeof(sSecretBaseItemsIndicesBuffer));
memset(sPlayerRoomItemsIndicesBuffer, 0, sizeof(sPlayerRoomItemsIndicesBuffer));
for (i = 0; i < ARRAY_COUNT(sSecretBaseItemsIndicesBuffer); i++)
{
if (gSaveBlock1Ptr->secretBases[0].decorations[i] != DECOR_NONE)
{
for (j = 0; j < gDecorationInventories[sCurDecorationCategory].size; j++)
{
if (gCurDecorationItems[j] == gSaveBlock1Ptr->secretBases[0].decorations[i])
{
for (k = 0; k < count && sSecretBaseItemsIndicesBuffer[k] != j + 1; k++)
;
if (k == count)
{
sSecretBaseItemsIndicesBuffer[count] = j + 1;
count++;
break;
}
}
}
}
}
count = 0;
for (i = 0; i < ARRAY_COUNT(sPlayerRoomItemsIndicesBuffer); i++)
{
if (gSaveBlock1Ptr->playerRoomDecorations[i] != DECOR_NONE)
{
for (j = 0; j < gDecorationInventories[sCurDecorationCategory].size; j++)
{
if (gCurDecorationItems[j] == gSaveBlock1Ptr->playerRoomDecorations[i] && IsDecorationIndexInSecretBase(j + 1) != TRUE)
{
for (k = 0; k < count && sPlayerRoomItemsIndicesBuffer[k] != j + 1; k++);
if (k == count)
{
sPlayerRoomItemsIndicesBuffer[count] = j + 1;
count++;
break;
}
}
}
}
}
}
static void IdentifyOwnedDecorationsCurrentlyInUse(u8 taskId)
{
IdentifyOwnedDecorationsCurrentlyInUseInternal(taskId);
}
bool8 IsSelectedDecorInThePC(void)
{
u16 i;
for (i = 0; i < ARRAY_COUNT(sSecretBaseItemsIndicesBuffer); i++)
{
if (sSecretBaseItemsIndicesBuffer[i] == sDecorationsScrollOffset + sDecorationsCursorPos + 1)
return FALSE;
if (i < ARRAY_COUNT(sPlayerRoomItemsIndicesBuffer)
&& sPlayerRoomItemsIndicesBuffer[i] == sDecorationsScrollOffset + sDecorationsCursorPos + 1)
{
return FALSE;
}
}
return TRUE;
}
static void Task_ShowDecorationItemsWindow(u8 taskId)
{
AddDecorationWindow(WINDOW_DECORATION_CATEGORIES);
ShowDecorationItemsWindow(taskId);
}
static void DontTossDecoration(u8 taskId)
{
ClearDialogWindowAndFrame(0, 0);
gTasks[taskId].func = Task_ShowDecorationItemsWindow;
}
static void ReturnToDecorationItemsAfterInvalidSelection(u8 taskId)
{
if (gMain.newKeys & (A_BUTTON | B_BUTTON))
{
ClearDialogWindowAndFrame(0, 0);
AddDecorationWindow(WINDOW_DECORATION_CATEGORIES);
ShowDecorationItemsWindow(taskId);
}
}
static void DecorationItemsMenuAction_Cancel(u8 taskId)
{
s16 *data = gTasks[taskId].data;
RemoveDecorationItemsScrollIndicators();
RemoveDecorationItemsOtherWindows();
DestroyListMenuTask(tMenuTaskId, NULL, NULL);
free(sDecorationItemsMenu);
ReinitDecorationCategoriesWindow(taskId);
}
static void SetInitialPositions(u8 taskId)
{
gTasks[taskId].tInitialX = gSaveBlock1Ptr->pos.x;
gTasks[taskId].tInitialY = gSaveBlock1Ptr->pos.y;
PlayerGetDestCoords(&gTasks[taskId].tCursorX, &gTasks[taskId].tCursorY);
}
static void WarpToInitialPosition(u8 taskId)
{
DrawWholeMapView();
SetWarpDestination(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1, gTasks[taskId].tInitialX, gTasks[taskId].tInitialY);
WarpIntoMap();
}
static u16 GetDecorationElevation(u8 decoration, u8 tileIndex)
{
u16 elevation = -1;
switch (decoration)
{
case DECOR_STAND:
elevation = sDecorationStandElevations[tileIndex] << METATILE_ELEVATION_SHIFT;
return elevation;
case DECOR_SLIDE:
elevation = sDecorationSlideElevation[tileIndex] << METATILE_ELEVATION_SHIFT;
return elevation;
default:
return elevation;
}
}
static void ShowDecorationOnMap_(u16 mapX, u16 mapY, u8 decWidth, u8 decHeight, u16 decoration)
{
u16 i, j;
s16 x, y;
u16 behavior;
u16 impassableFlag;
u16 overlapsWall;
u16 elevation;
for (j = 0; j < decHeight; j++)
{
y = mapY - decHeight + 1 + j;
for (i = 0; i < decWidth; i++)
{
x = mapX + i;
behavior = GetBehaviorByMetatileId(0x200 + gDecorations[decoration].tiles[j * decWidth + i]);
if (MetatileBehavior_IsSecretBaseImpassable(behavior) == TRUE || (gDecorations[decoration].permission != DECORPERM_PASS_FLOOR && (behavior >> METATILE_ELEVATION_SHIFT)))
impassableFlag = METATILE_COLLISION_MASK;
else
impassableFlag = 0;
// Choose the metatile that has the wall background instead of the floor if overlapping a wall.
if (gDecorations[decoration].permission != DECORPERM_NA_WALL && MetatileBehavior_IsSecretBaseNorthWall(MapGridGetMetatileBehaviorAt(x, y)) == TRUE)
overlapsWall = 1;
else
overlapsWall = 0;
elevation = GetDecorationElevation(gDecorations[decoration].id, j * decWidth + i);
if (elevation != 0xFFFF)
MapGridSetMetatileEntryAt(x, y, (gDecorations[decoration].tiles[j * decWidth + i] + (0x200 | overlapsWall)) | impassableFlag | elevation);
else
MapGridSetMetatileIdAt(x, y, (gDecorations[decoration].tiles[j * decWidth + i] + (0x200 | overlapsWall)) | impassableFlag);
}
}
}
void ShowDecorationOnMap(u16 mapX, u16 mapY, u16 decoration)
{
switch (gDecorations[decoration].shape)
{
case DECORSHAPE_1x1:
ShowDecorationOnMap_(mapX, mapY, 1, 1, decoration);
break;
case DECORSHAPE_2x1:
ShowDecorationOnMap_(mapX, mapY, 2, 1, decoration);
break;
case DECORSHAPE_3x1: // unused
ShowDecorationOnMap_(mapX, mapY, 3, 1, decoration);
break;
case DECORSHAPE_4x2:
ShowDecorationOnMap_(mapX, mapY, 4, 2, decoration);
break;
case DECORSHAPE_2x2:
ShowDecorationOnMap_(mapX, mapY, 2, 2, decoration);
break;
case DECORSHAPE_1x2:
ShowDecorationOnMap_(mapX, mapY, 1, 2, decoration);
break;
case DECORSHAPE_1x3: // unused
ShowDecorationOnMap_(mapX, mapY, 1, 3, decoration);
break;
case DECORSHAPE_2x4:
ShowDecorationOnMap_(mapX, mapY, 2, 4, decoration);
break;
case DECORSHAPE_3x3:
ShowDecorationOnMap_(mapX, mapY, 3, 3, decoration);
break;
case DECORSHAPE_3x2:
ShowDecorationOnMap_(mapX, mapY, 3, 2, decoration);
break;
}
}
void SetDecoration(void)
{
u8 i;
u8 j;
for (i = 0; i < NUM_DECORATION_FLAGS; i++)
{
if (FlagGet(FLAG_DECORATION_1 + i) == TRUE)
{
FlagClear(FLAG_DECORATION_1 + i);
for (j = 0; j < gMapHeader.events->objectEventCount; j++)
{
if (gMapHeader.events->objectEvents[j].flagId == FLAG_DECORATION_1 + i)
break;
}
VarSet(
VAR_OBJ_GFX_ID_0 + (gMapHeader.events->objectEvents[j].graphicsId - OBJ_EVENT_GFX_VAR_0),
sPlaceDecorationGraphicsDataBuffer.decoration->tiles[0]);
gSpecialVar_0x8005 = gMapHeader.events->objectEvents[j].localId;
gSpecialVar_0x8006 = sCurDecorMapX;
gSpecialVar_0x8007 = sCurDecorMapY;
TrySpawnObjectEvent(gSpecialVar_0x8005, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
TryMoveObjectEventToMapCoords(gSpecialVar_0x8005, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, gSpecialVar_0x8006, gSpecialVar_0x8007);
TryOverrideObjectEventTemplateCoords(gSpecialVar_0x8005, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
break;
}
}
}
static bool8 HasDecorationSpace(void)
{
u16 i;
for (i = 0; i < sDecorationContext.size; i++)
{
if (sDecorationContext.items[i] == DECOR_NONE)
return TRUE;
}
return FALSE;
}
static void DecorationItemsMenuAction_AttemptPlace(u8 taskId)
{
if (sDecorationContext.isPlayerRoom == TRUE && sCurDecorationCategory != DECORCAT_DOLL && sCurDecorationCategory != DECORCAT_CUSHION)
{
StringExpandPlaceholders(gStringVar4, gText_CantPlaceInRoom);
DisplayItemMessageOnField(taskId, gStringVar4, ReturnToDecorationItemsAfterInvalidSelection);
}
else if (IsSelectedDecorInThePC() == TRUE)
{
if (HasDecorationSpace() == TRUE)
{
FadeScreen(FADE_TO_BLACK, 0);
gTasks[taskId].tState = 0;
gTasks[taskId].func = Task_PlaceDecoration;
}
else
{
ConvertIntToDecimalStringN(gStringVar1, sDecorationContext.size, STR_CONV_MODE_RIGHT_ALIGN, 2);
if (sDecorationContext.isPlayerRoom == FALSE) {
StringExpandPlaceholders(gStringVar4, gText_NoMoreDecorations);
}
else
{
StringExpandPlaceholders(gStringVar4, gText_NoMoreDecorations2);
}
DisplayItemMessageOnField(taskId, gStringVar4, ReturnToDecorationItemsAfterInvalidSelection);
}
}
else
{
StringExpandPlaceholders(gStringVar4, gText_InUseAlready);
DisplayItemMessageOnField(taskId, gStringVar4, ReturnToDecorationItemsAfterInvalidSelection);
}
}
static void Task_PlaceDecoration(u8 taskId)
{
switch (gTasks[taskId].tState)
{
case 0:
if (!gPaletteFade.active)
{
SetInitialPositions(taskId);
gTasks[taskId].tState = 1;
}
break;
case 1:
gPaletteFade.bufferTransferDisabled = TRUE;
ConfigureCameraObjectForPlacingDecoration(&sPlaceDecorationGraphicsDataBuffer, gCurDecorationItems[gCurDecorationIndex]);
SetUpDecorationShape(taskId);
SetUpPlacingDecorationPlayerAvatar(taskId, &sPlaceDecorationGraphicsDataBuffer);
FadeInFromBlack();
gPaletteFade.bufferTransferDisabled = FALSE;
gTasks[taskId].tState = 2;
break;
case 2:
if (IsWeatherNotFadingIn() == TRUE)
{
gTasks[taskId].tDecorationItemsMenuCommand = DECOR_ITEMS_MENU_PLACE;
ContinueDecorating(taskId);
}
break;
}
}
static void ConfigureCameraObjectForPlacingDecoration(struct PlaceDecorationGraphicsDataBuffer *data, u8 decor)
{
sDecor_CameraSpriteObjectIdx1 = gSprites[gFieldCamera.spriteId].data[0];
gFieldCamera.spriteId = gpu_pal_decompress_alloc_tag_and_upload(data, decor);
gSprites[gFieldCamera.spriteId].oam.priority = 1;
gSprites[gFieldCamera.spriteId].callback = InitializePuttingAwayCursorSprite;
gSprites[gFieldCamera.spriteId].pos1.x = sDecorationMovementInfo[data->decoration->shape].cameraX;
gSprites[gFieldCamera.spriteId].pos1.y = sDecorationMovementInfo[data->decoration->shape].cameraY;
}
static void SetUpPlacingDecorationPlayerAvatar(u8 taskId, struct PlaceDecorationGraphicsDataBuffer *data)
{
u8 x;
x = 16 * (u8)gTasks[taskId].tDecorWidth + sDecorationMovementInfo[data->decoration->shape].cameraX - 8 * ((u8)gTasks[taskId].tDecorWidth - 1);
if (data->decoration->shape == DECORSHAPE_3x1 || data->decoration->shape == DECORSHAPE_3x3 || data->decoration->shape == DECORSHAPE_3x2)
x -= 8;
if (gSaveBlock2Ptr->playerGender == MALE)
sDecor_CameraSpriteObjectIdx2 = AddPseudoObjectEvent(OBJ_EVENT_GFX_BRENDAN_DECORATING, SpriteCallbackDummy, x, 72, 0);
else
sDecor_CameraSpriteObjectIdx2 = AddPseudoObjectEvent(OBJ_EVENT_GFX_MAY_DECORATING, SpriteCallbackDummy, x, 72, 0);
gSprites[sDecor_CameraSpriteObjectIdx2].oam.priority = 1;
DestroySprite(&gSprites[sDecor_CameraSpriteObjectIdx1]);
sDecor_CameraSpriteObjectIdx1 = gFieldCamera.spriteId;
}
static void SetUpDecorationShape(u8 taskId)
{
switch (gDecorations[gCurDecorationItems[gCurDecorationIndex]].shape)
{
case DECORSHAPE_1x1:
gTasks[taskId].tDecorWidth = 1;
gTasks[taskId].tDecorHeight = 1;
break;
case DECORSHAPE_2x1:
gTasks[taskId].tDecorWidth = 2;
gTasks[taskId].tDecorHeight = 1;
break;
case DECORSHAPE_3x1:
gTasks[taskId].tDecorWidth = 3;
gTasks[taskId].tDecorHeight = 1;
break;
case DECORSHAPE_4x2:
gTasks[taskId].tDecorWidth = 4;
gTasks[taskId].tDecorHeight = 2;
break;
case DECORSHAPE_2x2:
gTasks[taskId].tDecorWidth = 2;
gTasks[taskId].tDecorHeight = 2;
break;
case DECORSHAPE_1x2:
gTasks[taskId].tDecorWidth = 1;
gTasks[taskId].tDecorHeight = 2;
break;
case DECORSHAPE_1x3:
gTasks[taskId].tDecorWidth = 1;
gTasks[taskId].tDecorHeight = 3;
gTasks[taskId].tCursorY++;
break;
case DECORSHAPE_2x4:
gTasks[taskId].tDecorWidth = 2;
gTasks[taskId].tDecorHeight = 4;
break;
case DECORSHAPE_3x3:
gTasks[taskId].tDecorWidth = 3;
gTasks[taskId].tDecorHeight = 3;
break;
case DECORSHAPE_3x2:
gTasks[taskId].tDecorWidth = 3;
gTasks[taskId].tDecorHeight = 2;
break;
}
}
static void AttemptPlaceDecoration(u8 taskId)
{
gTasks[taskId].tButton = 0;
gSprites[sDecor_CameraSpriteObjectIdx1].data[7] = 1;
gSprites[sDecor_CameraSpriteObjectIdx2].data[7] = 1;
ResetCursorMovement();
AttemptPlaceDecoration_(taskId);
}
static void AttemptCancelPlaceDecoration(u8 taskId)
{
gTasks[taskId].tButton = 0;
gSprites[sDecor_CameraSpriteObjectIdx1].data[7] = 1;
gSprites[sDecor_CameraSpriteObjectIdx2].data[7] = 1;
ResetCursorMovement();
StringExpandPlaceholders(gStringVar4, gText_CancelDecorating);
DisplayItemMessageOnField(taskId, gStringVar4, CancelDecoratingPrompt);
}
// Note: behaviorBy is pre-anded with METATILE_ELEVATION_MASK.
static bool8 IsNonBlockNonElevated(u8 behaviorAt, u16 behaviorBy)
{
if (MetatileBehavior_IsBlockDecoration(behaviorAt) != TRUE || behaviorBy != 0)
return FALSE;
return TRUE;
}
static bool8 IsntInitialPosition(u8 taskId, s16 x, s16 y, u16 behaviorBy)
{
if (x == gTasks[taskId].tInitialX + 7 && y == gTasks[taskId].tInitialY + 7 && behaviorBy != 0)
return FALSE;
return TRUE;
}
static bool8 IsFloorOrBoardAndHole(u16 behaviorAt, const struct Decoration *decoration)
{
if (MetatileBehavior_IsBlockDecoration(behaviorAt) != TRUE)
{
if (decoration->id == DECOR_SOLID_BOARD && MetatileBehavior_IsSecretBaseHole(behaviorAt) == TRUE)
return TRUE;
if (MetatileBehavior_IsNormal(behaviorAt))
return TRUE;
}
return FALSE;
}
static bool8 CanPlaceDecoration(u8 taskId, const struct Decoration *decoration)
{
u8 i;
u8 j;
u8 behaviorAt;
u16 behaviorBy;
u8 mapY;
u8 mapX;
s16 curY;
s16 curX;
mapY = gTasks[taskId].tDecorHeight;
mapX = gTasks[taskId].tDecorWidth;
switch (decoration->permission)
{
case DECORPERM_SOLID_FLOOR:
case DECORPERM_PASS_FLOOR:
for (i = 0; i < mapY; i++)
{
curY = gTasks[taskId].tCursorY - i;
for (j = 0; j < mapX; j++)
{
curX = gTasks[taskId].tCursorX + j;
behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY);
behaviorBy = GetBehaviorByMetatileId(0x200 + decoration->tiles[(mapY - 1 - i) * mapX + j]) & METATILE_ELEVATION_MASK;
if (!IsFloorOrBoardAndHole(behaviorAt, decoration))
return FALSE;
if (!IsntInitialPosition(taskId, curX, curY, behaviorBy))
return FALSE;
behaviorAt = GetObjectEventIdByXYZ(curX, curY, 0);
if (behaviorAt != 0 && behaviorAt != 16)
return FALSE;
}
}
break;
case DECORPERM_BEHIND_FLOOR:
for (i = 0; i < mapY - 1; i++)
{
curY = gTasks[taskId].tCursorY - i;
for (j = 0; j < mapX; j++)
{
curX = gTasks[taskId].tCursorX + j;
behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY);
behaviorBy = GetBehaviorByMetatileId(0x200 + decoration->tiles[(mapY - 1 - i) * mapX + j]) & METATILE_ELEVATION_MASK;
if (!MetatileBehavior_IsNormal(behaviorAt) && !IsNonBlockNonElevated(behaviorAt, behaviorBy))
return FALSE;
if (!IsntInitialPosition(taskId, curX, curY, behaviorBy))
return FALSE;
if (GetObjectEventIdByXYZ(curX, curY, 0) != 16)
return FALSE;
}
}
curY = gTasks[taskId].tCursorY - mapY + 1;
for (j = 0; j < mapX; j++)
{
curX = gTasks[taskId].tCursorX + j;
behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY);
behaviorBy = GetBehaviorByMetatileId(0x200 + decoration->tiles[j]) & METATILE_ELEVATION_MASK;
if (!MetatileBehavior_IsNormal(behaviorAt) && !MetatileBehavior_IsSecretBaseNorthWall(behaviorAt))
return FALSE;
if (!IsntInitialPosition(taskId, curX, curY, behaviorBy))
return FALSE;
behaviorAt = GetObjectEventIdByXYZ(curX, curY, 0);
if (behaviorAt != 0 && behaviorAt != 16)
return FALSE;
}
break;
case DECORPERM_NA_WALL:
for (i = 0; i < mapY; i++)
{
curY = gTasks[taskId].tCursorY - i;
for (j = 0; j < mapX; j++)
{
curX = gTasks[taskId].tCursorX + j;
if (!MetatileBehavior_IsSecretBaseNorthWall(MapGridGetMetatileBehaviorAt(curX, curY)))
return FALSE;
if (MapGridGetMetatileIdAt(curX, curY + 1) == METATILE_SecretBase_SandOrnament_BrokenBase)
return FALSE;
}
}
break;
case DECORPERM_SPRITE:
curY = gTasks[taskId].tCursorY;
for (j = 0; j < mapX; j++)
{
curX = gTasks[taskId].tCursorX + j;
behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY);
if (decoration->shape == DECORSHAPE_1x2)
{
if (!MetatileBehavior_HoldsLargeDecoration(behaviorAt))
return FALSE;
}
else if (!MetatileBehavior_HoldsSmallDecoration(behaviorAt))
{
if (!MetatileBehavior_HoldsLargeDecoration(behaviorAt))
return FALSE;
}
if (GetObjectEventIdByXYZ(curX, curY, 0) != 16)
return FALSE;
}
break;
}
return TRUE;
}
static void AttemptPlaceDecoration_(u8 taskId)
{
if (CanPlaceDecoration(taskId, &gDecorations[gCurDecorationItems[gCurDecorationIndex]]) == TRUE)
{
StringExpandPlaceholders(gStringVar4, gText_PlaceItHere);
DisplayItemMessageOnField(taskId, gStringVar4, PlaceDecorationPrompt);
}
else
{
PlaySE(SE_FAILURE);
StringExpandPlaceholders(gStringVar4, gText_CantBePlacedHere);
DisplayItemMessageOnField(taskId, gStringVar4, CantPlaceDecorationPrompt);
}
}
static void PlaceDecorationPrompt(u8 taskId)
{
DisplayYesNoMenuDefaultYes();
DoYesNoFuncWithChoice(taskId, &sPlaceDecorationYesNoFunctions);
}
static void PlaceDecoration(u8 taskId)
{
ClearDialogWindowAndFrame(0, 0);
PlaceDecoration_(taskId);
if (gDecorations[gCurDecorationItems[gCurDecorationIndex]].permission != DECORPERM_SPRITE)
{
ShowDecorationOnMap(gTasks[taskId].tCursorX, gTasks[taskId].tCursorY, gCurDecorationItems[gCurDecorationIndex]);
}
else
{
sCurDecorMapX = gTasks[taskId].tCursorX - 7;
sCurDecorMapY = gTasks[taskId].tCursorY - 7;
ScriptContext1_SetupScript(SecretBase_EventScript_SetDecoration);
}
gSprites[sDecor_CameraSpriteObjectIdx1].pos1.y += 2;
if (gMapHeader.regionMapSectionId == MAPSEC_SECRET_BASE)
TV_PutSecretBaseVisitOnTheAir();
CancelDecorating_(taskId);
}
static void PlaceDecoration_(u8 taskId)
{
u16 i;
for (i = 0; i < sDecorationContext.size; i++)
{
if (sDecorationContext.items[i] == DECOR_NONE)
{
sDecorationContext.items[i] = gCurDecorationItems[gCurDecorationIndex];
sDecorationContext.pos[i] = ((gTasks[taskId].tCursorX - 7) << 4) + (gTasks[taskId].tCursorY - 7);
break;
}
}
if (!sDecorationContext.isPlayerRoom)
{
for (i = 0; i < DECOR_MAX_SECRET_BASE; i++)
{
if (sSecretBaseItemsIndicesBuffer[i] == DECOR_NONE)
{
sSecretBaseItemsIndicesBuffer[i] = gCurDecorationIndex + 1;
break;
}
}
}
else
{
for (i = 0; i < DECOR_MAX_PLAYERS_HOUSE; i++)
{
if (sPlayerRoomItemsIndicesBuffer[i] == DECOR_NONE)
{
sPlayerRoomItemsIndicesBuffer[i] = gCurDecorationIndex + 1;
break;
}
}
}
}
static void CancelDecoratingPrompt(u8 taskId)
{
DisplayYesNoMenuDefaultYes();
DoYesNoFuncWithChoice(taskId, &sCancelDecoratingYesNoFunctions);
}
static void CancelDecorating(u8 taskId)
{
ClearDialogWindowAndFrame(0, 0);
CancelDecorating_(taskId);
}
static void CancelDecorating_(u8 taskId)
{
FadeScreen(FADE_TO_BLACK, 0);
gTasks[taskId].tState = 0;
gTasks[taskId].func = c1_overworld_prev_quest;
}
static void c1_overworld_prev_quest(u8 taskId)
{
switch (gTasks[taskId].tState)
{
case 0:
ScriptContext2_Enable();
if (!gPaletteFade.active)
{
WarpToInitialPosition(taskId);
gTasks[taskId].tState = 1;
}
break;
case 1:
FreePlayerSpritePalette();
FreeSpritePaletteByTag(PLACE_DECORATION_SELECTOR_TAG);
gFieldCallback = FieldCB_InitDecorationItemsWindow;
SetMainCallback2(CB2_ReturnToField);
DestroyTask(taskId);
break;
}
}
static void Task_InitDecorationItemsWindow(u8 taskId)
{
s16 *data = gTasks[taskId].data;
switch (tState)
{
case 0:
HideSecretBaseDecorationSprites();
tState++;
break;
case 1:
ScriptContext1_SetupScript(SecretBase_EventScript_InitDecorations);
tState++;
break;
case 2:
ScriptContext2_Enable();
tState++;
break;
case 3:
if (IsWeatherNotFadingIn() == TRUE)
gTasks[taskId].func = HandleDecorationItemsMenuInput;
break;
}
}
static void FieldCB_InitDecorationItemsWindow(void)
{
u8 taskId;
ScriptContext2_Enable();
FadeInFromBlack();
taskId = CreateTask(Task_InitDecorationItemsWindow, 8);
AddDecorationItemsWindow(taskId);
gTasks[taskId].tState = 0;
}
static bool8 ApplyCursorMovement_IsInvalid(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (sDecorationLastDirectionMoved == DIR_SOUTH && tCursorY - tDecorHeight - 6 < 0)
{
tCursorY++;
return FALSE;
}
if (sDecorationLastDirectionMoved == DIR_NORTH && tCursorY - 7 >= gMapHeader.mapLayout->height)
{
tCursorY--;
return FALSE;
}
if (sDecorationLastDirectionMoved == DIR_WEST && tCursorX - 7 < 0)
{
tCursorX++;
return FALSE;
}
if (sDecorationLastDirectionMoved == DIR_EAST && tCursorX + tDecorWidth - 8 >= gMapHeader.mapLayout->width)
{
tCursorX--;
return FALSE;
}
return TRUE;
}
static bool8 IsHoldingDirection(void)
{
u16 heldKeys = gMain.heldKeys & DPAD_ANY;
if (heldKeys != DPAD_UP && heldKeys != DPAD_DOWN && heldKeys != DPAD_LEFT && heldKeys != DPAD_RIGHT)
return FALSE;
return TRUE;
}
static void ResetCursorMovement(void)
{
sDecorationLastDirectionMoved = 0;
gSprites[sDecor_CameraSpriteObjectIdx1].data[2] = 0;
gSprites[sDecor_CameraSpriteObjectIdx1].data[3] = 0;
}
static void Task_SelectLocation(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (!gSprites[sDecor_CameraSpriteObjectIdx1].data[4])
{
if (tButton == A_BUTTON)
{
sPlacePutAwayYesNoFunctions[tDecorationItemsMenuCommand].yesFunc(taskId);
return;
}
else if (tButton == B_BUTTON)
{
sPlacePutAwayYesNoFunctions[tDecorationItemsMenuCommand].noFunc(taskId);
return;
}
if ((gMain.heldKeys & DPAD_ANY) == DPAD_UP)
{
sDecorationLastDirectionMoved = DIR_SOUTH;
gSprites[sDecor_CameraSpriteObjectIdx1].data[2] = 0;
gSprites[sDecor_CameraSpriteObjectIdx1].data[3] = -2;
tCursorY--;
}
if ((gMain.heldKeys & DPAD_ANY) == DPAD_DOWN)
{
sDecorationLastDirectionMoved = DIR_NORTH;
gSprites[sDecor_CameraSpriteObjectIdx1].data[2] = 0;
gSprites[sDecor_CameraSpriteObjectIdx1].data[3] = 2;
tCursorY++;
}
if ((gMain.heldKeys & DPAD_ANY) == DPAD_LEFT)
{
sDecorationLastDirectionMoved = DIR_WEST;
gSprites[sDecor_CameraSpriteObjectIdx1].data[2] = -2;
gSprites[sDecor_CameraSpriteObjectIdx1].data[3] = 0;
tCursorX--;
}
if ((gMain.heldKeys & DPAD_ANY) == DPAD_RIGHT)
{
sDecorationLastDirectionMoved = DIR_EAST;
gSprites[sDecor_CameraSpriteObjectIdx1].data[2] = 2;
gSprites[sDecor_CameraSpriteObjectIdx1].data[3] = 0;
tCursorX++;
}
if (!IsHoldingDirection() || !ApplyCursorMovement_IsInvalid(taskId))
ResetCursorMovement();
}
if (sDecorationLastDirectionMoved)
{
gSprites[sDecor_CameraSpriteObjectIdx1].data[4]++;
gSprites[sDecor_CameraSpriteObjectIdx1].data[4] &= 7;
}
if (!tButton)
{
if (gMain.newKeys & A_BUTTON)
tButton = A_BUTTON;
if (gMain.newKeys & B_BUTTON)
tButton = B_BUTTON;
}
}
static void ContinueDecorating(u8 taskId)
{
ClearDialogWindowAndFrame(0, 1);
gSprites[sDecor_CameraSpriteObjectIdx1].data[7] = 0;
gTasks[taskId].tButton = 0;
gTasks[taskId].func = Task_SelectLocation;
}
static void CantPlaceDecorationPrompt(u8 taskId)
{
if (gMain.newKeys & A_BUTTON || gMain.newKeys & B_BUTTON)
ContinueDecorating(taskId);
}
static void ClearPlaceDecorationGraphicsDataBuffer(struct PlaceDecorationGraphicsDataBuffer *data)
{
CpuFill16(0, data, sizeof(*data));
}
static void CopyPalette(u16 *dest, u16 pal)
{
CpuFastCopy(&((u16 *)gTilesetPointer_SecretBase->palettes)[pal * 16], dest, sizeof(u16) * 16);
}
static void CopyTile(u8 *dest, u16 tile)
{
u8 buffer[TILE_SIZE_4BPP];
u16 mode;
u16 i;
mode = tile >> 10;
if (tile != 0)
tile &= 0x03FF;
CpuFastCopy(&((u8 *)gTilesetPointer_SecretBase->tiles)[tile * TILE_SIZE_4BPP], buffer, TILE_SIZE_4BPP);
switch (mode)
{
case 0:
CpuFastCopy(buffer, dest, TILE_SIZE_4BPP);
break;
case BG_TILE_H_FLIP(0) >> 10:
for (i = 0; i < 8; i++)
{
dest[4 * i] = (buffer[4 * (i + 1) - 1] >> 4) + ((buffer[4 * (i + 1) - 1] & 0x0F) << 4);
dest[4 * i + 1] = (buffer[4 * (i + 1) - 2] >> 4) + ((buffer[4 * (i + 1) - 2] & 0x0F) << 4);
dest[4 * i + 2] = (buffer[4 * (i + 1) - 3] >> 4) + ((buffer[4 * (i + 1) - 3] & 0x0F) << 4);
dest[4 * i + 3] = (buffer[4 * (i + 1) - 4] >> 4) + ((buffer[4 * (i + 1) - 4] & 0x0F) << 4);
}
break;
case BG_TILE_V_FLIP(0) >> 10:
for (i = 0; i < 8; i++)
{
dest[4 * i] = buffer[4 * (7 - i)];
dest[4 * i + 1] = buffer[4 * (7 - i) + 1];
dest[4 * i + 2] = buffer[4 * (7 - i) + 2];
dest[4 * i + 3] = buffer[4 * (7 - i) + 3];
}
break;
case BG_TILE_H_FLIP(BG_TILE_V_FLIP(0)) >> 10:
for (i = 0; i < 32; i++)
{
dest[i] = (buffer[31 - i] >> 4) + ((buffer[31 - i] & 0x0F) << 4);
}
break;
}
}
static void SetDecorSelectionBoxTiles(struct PlaceDecorationGraphicsDataBuffer *data)
{
u16 i;
for (i = 0; i < 64; i++)
CopyTile(&data->image[i * TILE_SIZE_4BPP], data->tiles[i]);
}
static u16 GetMetatile(u16 tile)
{
return ((u16 *)gTilesetPointer_SecretBaseRedCave->metatiles)[tile] & 0xFFF;
}
static void SetDecorSelectionMetatiles(struct PlaceDecorationGraphicsDataBuffer *data)
{
u8 i;
u8 shape;
shape = data->decoration->shape;
for (i = 0; i < gUnknown_085A71B0[shape].size; i++)
{
data->tiles[gUnknown_085A71B0[shape].tiles[i]] = GetMetatile(data->decoration->tiles[gUnknown_085A71B0[shape].y[i]] * 8 + gUnknown_085A71B0[shape].x[i]);
}
}
static void SetDecorSelectionBoxOamAttributes(u8 decorShape)
{
sDecorSelectorOam.y = 0;
sDecorSelectorOam.affineMode = ST_OAM_AFFINE_OFF;
sDecorSelectorOam.objMode = ST_OAM_OBJ_NORMAL;
sDecorSelectorOam.mosaic = 0;
sDecorSelectorOam.bpp = ST_OAM_4BPP;
sDecorSelectorOam.shape = sDecorationMovementInfo[decorShape].shape;
sDecorSelectorOam.x = 0;
sDecorSelectorOam.matrixNum = 0;
sDecorSelectorOam.size = sDecorationMovementInfo[decorShape].size;
sDecorSelectorOam.tileNum = 0;
sDecorSelectorOam.priority = 0;
sDecorSelectorOam.paletteNum = 0;
}
static void InitializePuttingAwayCursorSprite(struct Sprite *sprite)
{
sprite->data[2] = 0;
sprite->data[3] = 0;
sprite->data[4] = 0;
sprite->data[5] = 0;
sprite->data[6] = 0;
sprite->data[7] = 0;
sprite->callback = InitializePuttingAwayCursorSprite2;
}
static void InitializePuttingAwayCursorSprite2(struct Sprite *sprite)
{
if (sprite->data[7] == 0)
{
if (sprite->data[6] < 15)
sprite->invisible = 0;
else
sprite->invisible = 1;
sprite->data[6]++;
sprite->data[6] &= 0x1F;
}
else
{
sprite->invisible = FALSE;
}
}
static u8 gpu_pal_decompress_alloc_tag_and_upload(struct PlaceDecorationGraphicsDataBuffer *data, u8 decor)
{
ClearPlaceDecorationGraphicsDataBuffer(data);
data->decoration = &gDecorations[decor];
if (data->decoration->permission == DECORPERM_SPRITE)
return AddPseudoObjectEvent(data->decoration->tiles[0], SpriteCallbackDummy, 0, 0, 1);
FreeSpritePaletteByTag(PLACE_DECORATION_SELECTOR_TAG);
SetDecorSelectionMetatiles(data);
SetDecorSelectionBoxOamAttributes(data->decoration->shape);
SetDecorSelectionBoxTiles(data);
CopyPalette(data->palette, ((u16 *)gTilesetPointer_SecretBaseRedCave->metatiles)[(data->decoration->tiles[0] * 8) + 7] >> 12);
LoadSpritePalette(&sSpritePal_PlaceDecoration);
return CreateSprite(&sDecorationSelectorSpriteTemplate, 0, 0, 0);
}
static u8 AddDecorationIconObjectFromIconTable(u16 tilesTag, u16 paletteTag, u8 decor)
{
struct SpriteSheet sheet;
struct CompressedSpritePalette palette;
struct SpriteTemplate *template;
u8 spriteId;
if (!AllocItemIconTemporaryBuffers())
return MAX_SPRITES;
LZDecompressWram(GetDecorationIconPicOrPalette(decor, 0), gItemIconDecompressionBuffer);
CopyItemIconPicTo4x4Buffer(gItemIconDecompressionBuffer, gItemIcon4x4Buffer);
sheet.data = gItemIcon4x4Buffer;
sheet.size = 0x200;
sheet.tag = tilesTag;
LoadSpriteSheet(&sheet);
palette.data = GetDecorationIconPicOrPalette(decor, 1);
palette.tag = paletteTag;
LoadCompressedSpritePalette(&palette);
template = malloc(sizeof(struct SpriteTemplate));
*template = gItemIconSpriteTemplate;
template->tileTag = tilesTag;
template->paletteTag = paletteTag;
spriteId = CreateSprite(template, 0, 0, 0);
FreeItemIconTemporaryBuffers();
free(template);
return spriteId;
}
static const u32 *GetDecorationIconPicOrPalette(u16 decor, u8 mode)
{
if (decor > NUM_DECORATIONS)
decor = DECOR_NONE;
return gDecorIconTable[decor][mode];
}
static u8 AddDecorationIconObjectFromObjectEvent(u16 tilesTag, u16 paletteTag, u8 decor)
{
u8 spriteId;
struct SpriteSheet sheet;
struct SpritePalette palette;
struct SpriteTemplate *template;
ClearPlaceDecorationGraphicsDataBuffer(&sPlaceDecorationGraphicsDataBuffer);
sPlaceDecorationGraphicsDataBuffer.decoration = &gDecorations[decor];
if (sPlaceDecorationGraphicsDataBuffer.decoration->permission != DECORPERM_SPRITE)
{
SetDecorSelectionMetatiles(&sPlaceDecorationGraphicsDataBuffer);
SetDecorSelectionBoxOamAttributes(sPlaceDecorationGraphicsDataBuffer.decoration->shape);
SetDecorSelectionBoxTiles(&sPlaceDecorationGraphicsDataBuffer);
CopyPalette(sPlaceDecorationGraphicsDataBuffer.palette, ((u16 *)gTilesetPointer_SecretBaseRedCave->metatiles)[(sPlaceDecorationGraphicsDataBuffer.decoration->tiles[0] * 8) + 7] >> 12);
sheet.data = sPlaceDecorationGraphicsDataBuffer.image;
sheet.size = sDecorShapeSizes[sPlaceDecorationGraphicsDataBuffer.decoration->shape] * TILE_SIZE_4BPP;
sheet.tag = tilesTag;
LoadSpriteSheet(&sheet);
palette.data = sPlaceDecorationGraphicsDataBuffer.palette;
palette.tag = paletteTag;
LoadSpritePalette(&palette);
template = Alloc(sizeof(struct SpriteTemplate));
*template = sDecorWhilePlacingSpriteTemplate;
template->tileTag = tilesTag;
template->paletteTag = paletteTag;
spriteId = CreateSprite(template, 0, 0, 0);
free(template);
}
else
{
spriteId = AddPseudoObjectEvent(sPlaceDecorationGraphicsDataBuffer.decoration->tiles[0], SpriteCallbackDummy, 0, 0, 1);
}
return spriteId;
}
u8 AddDecorationIconObject(u8 decor, s16 x, s16 y, u8 priority, u16 tilesTag, u16 paletteTag)
{
u8 spriteId;
if (decor > NUM_DECORATIONS)
{
spriteId = AddDecorationIconObjectFromIconTable(tilesTag, paletteTag, DECOR_NONE);
if (spriteId == MAX_SPRITES)
return MAX_SPRITES;
gSprites[spriteId].pos2.x = x + 4;
gSprites[spriteId].pos2.y = y + 4;
}
else if (gDecorIconTable[decor][0] == NULL)
{
spriteId = AddDecorationIconObjectFromObjectEvent(tilesTag, paletteTag, decor);
if (spriteId == MAX_SPRITES)
return MAX_SPRITES;
gSprites[spriteId].pos2.x = x;
if (decor == DECOR_SILVER_SHIELD || decor == DECOR_GOLD_SHIELD)
gSprites[spriteId].pos2.y = y - 4;
else
gSprites[spriteId].pos2.y = y;
}
else
{
spriteId = AddDecorationIconObjectFromIconTable(tilesTag, paletteTag, decor);
if (spriteId == MAX_SPRITES)
return MAX_SPRITES;
gSprites[spriteId].pos2.x = x + 4;
gSprites[spriteId].pos2.y = y + 4;
}
gSprites[spriteId].oam.priority = priority;
return spriteId;
}
static void ClearDecorationContextIndex(u8 idx)
{
sDecorationContext.items[idx] = DECOR_NONE;
sDecorationContext.pos[idx] = 0;
}
// Input
// gSpecialVar_0x8004: Current iteration.
//
// Output
// gSpecialVar_Result: TRUE if all iterations complete.
// gSpecialVar_0x8005: flagId of decoration (if any).
// gSpecialVar_0x8006: localId of decoration object event (if any).
void PutAwayDecorationIteration(void)
{
u16 i;
gSpecialVar_0x8005 = 0;
gSpecialVar_Result = FALSE;
if (gSpecialVar_0x8004 == sCurDecorSelectedInRearrangement)
{
gSpecialVar_Result = TRUE;
}
else if (gDecorations[sDecorationContext.items[sDecorRearrangementDataBuffer[gSpecialVar_0x8004].idx]].permission == DECORPERM_SPRITE)
{
gSpecialVar_0x8005 = sDecorRearrangementDataBuffer[gSpecialVar_0x8004].flagId;
ClearDecorationContextIndex(sDecorRearrangementDataBuffer[gSpecialVar_0x8004].idx);
for (i = 0; i < gMapHeader.events->objectEventCount; i++)
{
if (gMapHeader.events->objectEvents[i].flagId == gSpecialVar_0x8005)
{
gSpecialVar_0x8006 = gMapHeader.events->objectEvents[i].localId;
break;
}
}
}
}
// Unused
void GetObjectEventLocalIdByFlag(void)
{
u8 i;
for (i = 0; i < gMapHeader.events->objectEventCount; i++)
{
if (gMapHeader.events->objectEvents[i].flagId == gSpecialVar_0x8004)
{
gSpecialVar_0x8005 = gMapHeader.events->objectEvents[i].localId;
break;
}
}
}
static void ClearRearrangementNonSprites(void)
{
u8 i;
u8 y;
u8 x;
int posX;
int posY;
u8 perm;
for (i = 0; i < sCurDecorSelectedInRearrangement; i++)
{
perm = gDecorations[sDecorationContext.items[sDecorRearrangementDataBuffer[i].idx]].permission;
posX = sDecorationContext.pos[sDecorRearrangementDataBuffer[i].idx] >> 4;
posY = sDecorationContext.pos[sDecorRearrangementDataBuffer[i].idx] & 0x0F;
if (perm != DECORPERM_SPRITE)
{
for (y = 0; y < sDecorRearrangementDataBuffer[i].height; y++)
{
for (x = 0; x < sDecorRearrangementDataBuffer[i].width; x++)
{
MapGridSetMetatileEntryAt(posX + 7 + x, posY + 7 - y, gMapHeader.mapLayout->map[posX + x + gMapHeader.mapLayout->width * (posY - y)] | 0x3000);
}
}
ClearDecorationContextIndex(sDecorRearrangementDataBuffer[i].idx);
}
}
}
static void Task_PutAwayDecoration(u8 taskId)
{
switch (gTasks[taskId].tState)
{
case 0:
ClearRearrangementNonSprites();
gTasks[taskId].tState = 1;
break;
case 1:
if (!gPaletteFade.active) {
DrawWholeMapView();
ScriptContext1_SetupScript(SecretBase_EventScript_PutAwayDecoration);
ClearDialogWindowAndFrame(0, 1);
gTasks[taskId].tState = 2;
}
break;
case 2:
ScriptContext2_Enable();
IdentifyOwnedDecorationsCurrentlyInUseInternal(taskId);
FadeInFromBlack();
gTasks[taskId].tState = 3;
break;
case 3:
if (IsWeatherNotFadingIn() == TRUE)
{
StringExpandPlaceholders(gStringVar4, gText_DecorationReturnedToPC);
DisplayItemMessageOnField(taskId, gStringVar4, ContinuePuttingAwayDecorationsPrompt);
if (gMapHeader.regionMapSectionId == MAPSEC_SECRET_BASE)
TV_PutSecretBaseVisitOnTheAir();
}
break;
}
}
static bool8 HasDecorationsInUse(u8 taskId)
{
u16 i;
for (i = 0; i < sDecorationContext.size; i++)
{
if (sDecorationContext.items[i] != DECOR_NONE)
return TRUE;
}
return FALSE;
}
static void SetUpPuttingAwayDecorationPlayerAvatar(void)
{
GetPlayerFacingDirection();
sDecor_CameraSpriteObjectIdx1 = gSprites[gFieldCamera.spriteId].data[0];
LoadPlayerSpritePalette();
gFieldCamera.spriteId = CreateSprite(&sPuttingAwayCursorSpriteTemplate, 120, 80, 0);
if (gSaveBlock2Ptr->playerGender == MALE)
sDecor_CameraSpriteObjectIdx2 = AddPseudoObjectEvent(OBJ_EVENT_GFX_BRENDAN_DECORATING, SpriteCallbackDummy, 136, 72, 0);
else
sDecor_CameraSpriteObjectIdx2 = AddPseudoObjectEvent(OBJ_EVENT_GFX_MAY_DECORATING, SpriteCallbackDummy, 136, 72, 0);
gSprites[sDecor_CameraSpriteObjectIdx2].oam.priority = 1;
DestroySprite(&gSprites[sDecor_CameraSpriteObjectIdx1]);
sDecor_CameraSpriteObjectIdx1 = gFieldCamera.spriteId;
gSprites[sDecor_CameraSpriteObjectIdx1].oam.priority = 1;
}
static void Task_ContinuePuttingAwayDecorations(u8 taskId)
{
s16 *data;
data = gTasks[taskId].data;
switch (tState)
{
case 0:
if (!gPaletteFade.active)
{
SetInitialPositions(taskId);
tState = 1;
tDecorHeight = 1;
tDecorWidth = 1;
}
break;
case 1:
SetUpPuttingAwayDecorationPlayerAvatar();
FadeInFromBlack();
tState = 2;
break;
case 2:
if (IsWeatherNotFadingIn() == TRUE)
{
tDecorationItemsMenuCommand = DECOR_ITEMS_MENU_PUT_AWAY;
ContinuePuttingAwayDecorations(taskId);
}
break;
}
}
static void ContinuePuttingAwayDecorations(u8 taskId)
{
ClearDialogWindowAndFrame(0, 1);
gSprites[sDecor_CameraSpriteObjectIdx1].data[7] = 0;
gSprites[sDecor_CameraSpriteObjectIdx1].invisible = FALSE;
gSprites[sDecor_CameraSpriteObjectIdx1].callback = InitializeCameraSprite1;
gSprites[sDecor_CameraSpriteObjectIdx2].pos1.x = 136;
gSprites[sDecor_CameraSpriteObjectIdx2].pos1.y = 72;
gTasks[taskId].tButton = 0;
gTasks[taskId].func = Task_SelectLocation;
}
static void AttemptPutAwayDecoration(u8 taskId)
{
gTasks[taskId].tButton = 0;
ResetCursorMovement();
AttemptPutAwayDecoration_(taskId);
}
static void AttemptCancelPutAwayDecoration(u8 taskId)
{
gTasks[taskId].tButton = 0;
ResetCursorMovement();
gSprites[sDecor_CameraSpriteObjectIdx1].invisible = FALSE;
gSprites[sDecor_CameraSpriteObjectIdx1].callback = SpriteCallbackDummy;
StringExpandPlaceholders(gStringVar4, gText_StopPuttingAwayDecorations);
DisplayItemMessageOnField(taskId, gStringVar4, StopPuttingAwayDecorationsPrompt);
}
static void AttemptPutAwayDecoration_(u8 taskId)
{
s16 *data;
u8 behavior;
AttemptMarkDecorUnderCursorForRemoval(taskId);
if (sCurDecorSelectedInRearrangement != 0)
{
StringExpandPlaceholders(gStringVar4, gText_ReturnDecorationToPC);
DisplayItemMessageOnField(taskId, gStringVar4, ReturnDecorationPrompt);
}
else
{
data = gTasks[taskId].data;
behavior = MapGridGetMetatileBehaviorAt(tCursorX, tCursorY);
if (MetatileBehavior_IsSecretBasePC(behavior) == TRUE || MetatileBehavior_IsPlayerRoomPCOn(behavior) == TRUE)
{
gSprites[sDecor_CameraSpriteObjectIdx1].invisible = FALSE;
gSprites[sDecor_CameraSpriteObjectIdx1].callback = SpriteCallbackDummy;
StringExpandPlaceholders(gStringVar4, gText_StopPuttingAwayDecorations);
DisplayItemMessageOnField(taskId, gStringVar4, StopPuttingAwayDecorationsPrompt);
}
else
{
StringExpandPlaceholders(gStringVar4, gText_NoDecorationHere);
DisplayItemMessageOnField(taskId, gStringVar4, ContinuePuttingAwayDecorationsPrompt);
}
}
}
static void ContinuePuttingAwayDecorationsPrompt(u8 taskId)
{
if (gMain.newKeys & A_BUTTON || gMain.newKeys & B_BUTTON)
ContinuePuttingAwayDecorations(taskId);
}
static void SetDecorRearrangementShape(u8 decor, struct DecorRearrangementDataBuffer *data)
{
if (gDecorations[decor].shape == DECORSHAPE_1x1)
{
data->width = 1;
data->height = 1;
}
else if (gDecorations[decor].shape == DECORSHAPE_2x1)
{
data->width = 2;
data->height = 1;
}
else if (gDecorations[decor].shape == DECORSHAPE_3x1)
{
data->width = 3;
data->height = 1;
}
else if (gDecorations[decor].shape == DECORSHAPE_4x2)
{
data->width = 4;
data->height = 2;
}
else if (gDecorations[decor].shape == DECORSHAPE_2x2)
{
data->width = 2;
data->height = 2;
}
else if (gDecorations[decor].shape == DECORSHAPE_1x2)
{
data->width = 1;
data->height = 2;
}
else if (gDecorations[decor].shape == DECORSHAPE_1x3)
{
data->width = 1;
data->height = 3;
}
else if (gDecorations[decor].shape == DECORSHAPE_2x4)
{
data->width = 2;
data->height = 4;
}
else if (gDecorations[decor].shape == DECORSHAPE_3x3)
{
data->width = 3;
data->height = 3;
}
else if (gDecorations[decor].shape == DECORSHAPE_3x2)
{
data->width = 3;
data->height = 2;
}
}
static void SetCameraSpritePosition(u8 x, u8 y)
{
gSprites[sDecor_CameraSpriteObjectIdx1].invisible = TRUE;
gSprites[sDecor_CameraSpriteObjectIdx1].callback = SpriteCallbackDummy;
gSprites[sDecor_CameraSpriteObjectIdx2].pos1.x = x * 16 + 136;
gSprites[sDecor_CameraSpriteObjectIdx2].pos1.y = y * 16 + 72;
}
static bool8 DecorationIsUnderCursor(u8 taskId, u8 idx, struct DecorRearrangementDataBuffer *data)
{
u8 x;
u8 y;
u8 xOff;
u8 yOff;
u8 ht;
x = gTasks[taskId].tCursorX - 7;
y = gTasks[taskId].tCursorY - 7;
xOff = sDecorationContext.pos[idx] >> 4;
yOff = sDecorationContext.pos[idx] & 0x0F;
ht = data->height;
if (sDecorationContext.items[idx] == DECOR_SAND_ORNAMENT && MapGridGetMetatileIdAt(xOff + 7, yOff + 7) == METATILE_SecretBase_SandOrnament_BrokenBase)
ht--;
if (x >= xOff && x < xOff + data->width && y > yOff - ht && y <= yOff)
{
SetCameraSpritePosition(data->width - (x - xOff + 1), yOff - y);
return TRUE;
}
return FALSE;
}
static void SetDecorRearrangementFlagIdIfFlagUnset(void)
{
u8 xOff;
u8 yOff;
u16 i;
xOff = sDecorationContext.pos[sDecorRearrangementDataBuffer[sCurDecorSelectedInRearrangement].idx] >> 4;
yOff = sDecorationContext.pos[sDecorRearrangementDataBuffer[sCurDecorSelectedInRearrangement].idx] & 0x0F;
for (i = 0; i < OBJECT_EVENT_TEMPLATES_COUNT; i++)
{
if (gSaveBlock1Ptr->objectEventTemplates[i].x == xOff && gSaveBlock1Ptr->objectEventTemplates[i].y == yOff && !FlagGet(gSaveBlock1Ptr->objectEventTemplates[i].flagId))
{
sDecorRearrangementDataBuffer[sCurDecorSelectedInRearrangement].flagId = gSaveBlock1Ptr->objectEventTemplates[i].flagId;
break;
}
}
}
static bool8 AttemptMarkSpriteDecorUnderCursorForRemoval(u8 taskId)
{
u16 i;
for (i = 0; i < sDecorationContext.size; i++)
{
if (sDecorationContext.items[i] != DECOR_NONE)
{
if (gDecorations[sDecorationContext.items[i]].permission == DECORPERM_SPRITE)
{
SetDecorRearrangementShape(sDecorationContext.items[i], sDecorRearrangementDataBuffer);
if (DecorationIsUnderCursor(taskId, i, sDecorRearrangementDataBuffer) == TRUE)
{
sDecorRearrangementDataBuffer->idx = i;
SetDecorRearrangementFlagIdIfFlagUnset();
sCurDecorSelectedInRearrangement = 1;
return TRUE;
}
}
}
}
return FALSE;
}
static void MarkSpriteDecorsInBoundsForRemoval(u8 left, u8 top, u8 right, u8 bottom)
{
u8 i;
u8 xOff;
u8 yOff;
u8 decor;
for (i = 0; i < sDecorationContext.size; i++)
{
decor = sDecorationContext.items[i];
xOff = sDecorationContext.pos[i] >> 4;
yOff = sDecorationContext.pos[i] & 0x0F;
if (decor != DECOR_NONE && gDecorations[decor].permission == DECORPERM_SPRITE && left <= xOff && top <= yOff && right >= xOff && bottom >= yOff)
{
sDecorRearrangementDataBuffer[sCurDecorSelectedInRearrangement].idx = i;
SetDecorRearrangementFlagIdIfFlagUnset();
sCurDecorSelectedInRearrangement++;
}
}
}
static void AttemptMarkDecorUnderCursorForRemoval(u8 taskId)
{
u8 i;
u8 xOff;
u8 yOff;
u8 var1;
u32 var2;
sCurDecorSelectedInRearrangement = 0;
if (AttemptMarkSpriteDecorUnderCursorForRemoval(taskId) != TRUE)
{
// Not a sprite.
for (i = 0; i < sDecorationContext.size; i++)
{
var1 = sDecorationContext.items[i];
if (var1 != DECOR_NONE)
{
SetDecorRearrangementShape(var1, &sDecorRearrangementDataBuffer[0]);
if (DecorationIsUnderCursor(taskId, i, &sDecorRearrangementDataBuffer[0]) == TRUE)
{
sDecorRearrangementDataBuffer[0].idx = i;
sCurDecorSelectedInRearrangement++;
break;
}
}
}
if (sCurDecorSelectedInRearrangement != 0)
{
xOff = sDecorationContext.pos[sDecorRearrangementDataBuffer[0].idx] >> 4;
yOff = sDecorationContext.pos[sDecorRearrangementDataBuffer[0].idx] & 0x0F;
var1 = yOff - sDecorRearrangementDataBuffer[0].height + 1;
var2 = sDecorRearrangementDataBuffer[0].width + xOff - 1;
// Remove any dolls/cushions on this decoration.
MarkSpriteDecorsInBoundsForRemoval(xOff, var1, var2, yOff);
}
}
}
static void ReturnDecorationPrompt(u8 taskId)
{
DisplayYesNoMenuDefaultYes();
DoYesNoFuncWithChoice(taskId, &sReturnDecorationYesNoFunctions);
}
static void PutAwayDecoration(u8 taskId)
{
FadeScreen(FADE_TO_BLACK, 0);
gTasks[taskId].tState = 0;
gTasks[taskId].func = Task_PutAwayDecoration;
}
static void StopPuttingAwayDecorationsPrompt(u8 taskId)
{
DisplayYesNoMenuDefaultYes();
DoYesNoFuncWithChoice(taskId, &sStopPuttingAwayDecorationsYesNoFunctions);
}
static void StopPuttingAwayDecorations(u8 taskId)
{
ClearDialogWindowAndFrame(0, 0);
StopPuttingAwayDecorations_(taskId);
}
static void StopPuttingAwayDecorations_(u8 taskId)
{
FadeScreen(FADE_TO_BLACK, 0);
gTasks[taskId].tState = 0;
gTasks[taskId].func = Task_StopPuttingAwayDecorations;
}
static void Task_StopPuttingAwayDecorations(u8 taskId)
{
switch (gTasks[taskId].tState)
{
case 0:
if (!gPaletteFade.active)
{
WarpToInitialPosition(taskId);
gTasks[taskId].tState = 1;
}
break;
case 1:
FreePlayerSpritePalette();
gFieldCallback = FieldCB_StopPuttingAwayDecorations;
SetMainCallback2(CB2_ReturnToField);
DestroyTask(taskId);
break;
}
}
static void Task_ReinitializeDecorationMenuHandler(u8 taskId)
{
s16 *data = gTasks[taskId].data;
switch (tState)
{
case 0:
HideSecretBaseDecorationSprites();
tState++;
break;
case 1:
ScriptContext1_SetupScript(SecretBase_EventScript_InitDecorations);
tState++;
break;
case 2:
ScriptContext2_Enable();
tState++;
break;
case 3:
if (IsWeatherNotFadingIn() == TRUE)
gTasks[taskId].func = HandleDecorationActionsMenuInput;
break;
}
}
static void FieldCB_StopPuttingAwayDecorations(void)
{
u8 taskId;
FadeInFromBlack();
DrawDialogueFrame(0, 1);
InitDecorationActionsWindow();
taskId = CreateTask(Task_ReinitializeDecorationMenuHandler, 8);
gTasks[taskId].tState = 0;
}
static void InitializeCameraSprite1(struct Sprite *sprite)
{
sprite->data[0]++;
sprite->data[0] &= 0x1F;
if (sprite->data[0] > 15)
sprite->invisible = TRUE;
else
sprite->invisible = FALSE;
}
static void LoadPlayerSpritePalette(void)
{
if (gSaveBlock2Ptr->playerGender == MALE)
LoadSpritePalette(&sSpritePal_PuttingAwayCursorBrendan);
else
LoadSpritePalette(&sSpritePal_PuttingAwayCursorMay);
}
static void FreePlayerSpritePalette(void)
{
FreeSpritePaletteByTag(PLACE_DECORATION_PLAYER_TAG);
}
static void DecorationItemsMenuAction_AttemptToss(u8 taskId)
{
if (IsSelectedDecorInThePC() == TRUE)
{
StringCopy(gStringVar1, gDecorations[gCurDecorationItems[gCurDecorationIndex]].name);
StringExpandPlaceholders(gStringVar4, gText_DecorationWillBeDiscarded);
DisplayItemMessageOnField(taskId, gStringVar4, TossDecorationPrompt);
}
else
{
StringExpandPlaceholders(gStringVar4, gText_CantThrowAwayInUse);
DisplayItemMessageOnField(taskId, gStringVar4, ReturnToDecorationItemsAfterInvalidSelection);
}
}
static void TossDecorationPrompt(u8 taskId)
{
DisplayYesNoMenuDefaultYes();
DoYesNoFuncWithChoice(taskId, &sTossDecorationYesNoFunctions);
}
static void TossDecoration(u8 taskId)
{
gCurDecorationItems[gCurDecorationIndex] = DECOR_NONE;
sNumOwnedDecorationsInCurCategory = GetNumOwnedDecorationsInCategory(sCurDecorationCategory);
CondenseDecorationsInCategory(sCurDecorationCategory);
IdentifyOwnedDecorationsCurrentlyInUseInternal(taskId);
StringExpandPlaceholders(gStringVar4, gText_DecorationThrownAway);
DisplayItemMessageOnField(taskId, gStringVar4, ReturnToDecorationItemsAfterInvalidSelection);
}