#include "global.h" #include "alloc.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 "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 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; }; EWRAM_DATA u8 *gCurDecorationItems = NULL; EWRAM_DATA static u8 sDecorationActionsCursorPos = 0; EWRAM_DATA static u8 sNumOwnedDecorationsInCurCategory = 0; EWRAM_DATA static u8 sSecretBaseItemsIndicesBuffer[16] = {}; EWRAM_DATA static u8 sPlayerRoomItemsIndicesBuffer[12] = {}; 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 struct DecorationPCContext gDecorationContext = {}; EWRAM_DATA static u8 sDecorMenuWindowIds[4] = {}; EWRAM_DATA static struct DecorationItemsMenu *sDecorationItemsMenu = NULL; EWRAM_DATA 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[16] = {}; 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); void sub_81274A0(u8 a0, s32 a1, u8 a2); static void ShowDecorationItemsWindow(u8 taskId); static void HandleDecorationItemsMenuInput(u8 taskId); static void PrintDecorationItemDescription(u32 itemIndex); static void RemoveDecorationItemsOtherWindows(void); bool8 sub_81277BC(u8 idx); bool8 sub_81277E8(u8 idx); static void IdentifyOwnedDecorationsCurrentlyInUse(u8 taskId); static void InitDecorationItemsWindow(u8 taskId); static void ShowDecorationCategorySummaryWindow(u8 category); void sub_8127A30(u8 taskId); void sub_8127A8C(u8 taskId); void sub_8127F68(u8 taskId); void sub_8128060(u8 taskId); void ConfigureCameraObjectForPlacingDecoration(struct PlaceDecorationGraphicsDataBuffer *data, u8 decor); void SetUpPlacingDecorationPlayerAvatar(u8 taskId, struct PlaceDecorationGraphicsDataBuffer *data); void sub_812826C(u8 taskId); void sub_81283BC(u8 taskId); void sub_8128414(u8 taskId); void sub_8128950(u8 taskId); void sub_81289D0(u8 taskId); void sub_81289F0(u8 taskId); void sub_8128AAC(u8 taskId); void sub_8128B80(u8 taskId); void sub_8128BA0(u8 taskId); void sub_8128BBC(u8 taskId); void c1_overworld_prev_quest(u8 taskId); void sub_8128CD4(void); void sub_8128DE0(void); void sub_8128FD8(u8 taskId); void sub_8129020(u8 taskId); void sub_81292D0(struct Sprite *sprite); void sub_81292E8(struct Sprite *sprite); u8 gpu_pal_decompress_alloc_tag_and_upload(struct PlaceDecorationGraphicsDataBuffer *data, u8 decor); const u32 *GetDecorationIconPicOrPalette(u16 decor, u8 mode); bool8 sub_81299AC(u8 taskId); void sub_8129ABC(u8 taskId); void sub_8129B34(u8 taskId); void sub_8129BCC(u8 taskId); void sub_8129BF8(u8 taskId); void sub_8129C74(u8 taskId); void sub_8129D64(u8 taskId); void sub_812A0E8(u8 taskId); void sub_812A1A0(u8 taskId); void sub_812A1C0(u8 taskId); void sub_812A1F0(u8 taskId); void sub_812A210(u8 taskId); void sub_812A22C(u8 taskId); void sub_812A25C(u8 taskId); void sub_812A334(void); void sub_812A36C(struct Sprite *sprite); void sub_812A39C(void); void sub_812A3C8(void); void sub_812A3D4(u8 taskId); void sub_812A458(u8 taskId); void sub_812A478(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] = { { sub_8127F68, sub_8127A8C }, { sub_812A3D4, sub_8127A8C }, { sub_8133DA0, sub_8127A8C }, }; static const struct WindowTemplate sDecorationWindowTemplates[4] = { { .bg = 0, .tilemapLeft = 1, .tilemapTop = 1, .width = 18, .height = 8, .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 = sub_81274A0, .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 }; const struct SpriteTemplate sDecorWhilePlacingSpriteTemplate = { 0x0000, 0x0000, &sDecorSelectorOam, sDecorSelectorAnimCmds, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy }; const struct SpritePalette gUnknown_085A72BC = { .data = (const u16 *)&sPlaceDecorationGraphicsDataBuffer.palette, .tag = PLACE_DECORATION_SELECTOR_TAG, }; const struct YesNoFuncTable gUnknown_085A72C4 = { .yesFunc = sub_81289F0, .noFunc = sub_8128FD8, }; const struct YesNoFuncTable gUnknown_085A72CC = { .yesFunc = sub_8128BA0, .noFunc = sub_8128FD8, }; const struct YesNoFuncTable gUnknown_085A72D4[] = { { .yesFunc = sub_81283BC, .noFunc = sub_8128414, }, { .yesFunc = sub_8129BCC, .noFunc = sub_8129BF8, } }; static const u8 sDecorationStandElevations[] = { 4, 4, 4, 4, 0, 3, 3, 0 }; static const u8 sDecorationSlideElevation[] = { 4, 4, 4, 4, 0, 4, 3, 0, }; const u16 gUnknown_085A72F4[] = { 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x10, 0x20, 0x40, 0x20 }; const u16 gUnknown_085A7308[] = INCBIN_U16("graphics/decorations/unk_85a7308.gbapal"); const u16 gUnknown_085A7328[] = INCBIN_U16("graphics/decorations/unk_85a7328.gbapal"); const struct YesNoFuncTable gUnknown_085A7348 = { .yesFunc = sub_812A1C0, .noFunc = sub_8129B34, }; const struct YesNoFuncTable gUnknown_085A7350 = { .yesFunc = sub_812A210, .noFunc = sub_8129B34, }; const u8 gUnknown_085A7358[] = INCBIN_U8("graphics/misc/decoration_unk_85a7358.4bpp"); const struct SpritePalette gUnknown_085A73D8 = { .data = gUnknown_085A7308, .tag = PLACE_DECORATION_PLAYER_TAG, }; const struct SpritePalette gUnknown_085A73E0 = { .data = gUnknown_085A7328, .tag = PLACE_DECORATION_PLAYER_TAG, }; const struct OamData gUnknown_085A73E8 = { .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, }; const union AnimCmd gUnknown_085A73F0[] = { ANIMCMD_FRAME(0, 0, 0), ANIMCMD_END }; const union AnimCmd *const gUnknown_085A73F8[] = { gUnknown_085A73F0, }; const struct SpriteFrameImage gUnknown_085A73FC = { .data = gUnknown_085A7358, .size = 0x80, }; const struct SpriteTemplate gUnknown_085A7404 = { 0xFFFF, PLACE_DECORATION_PLAYER_TAG, &gUnknown_085A73E8, gUnknown_085A73F8, &gUnknown_085A73FC, gDummySpriteAffineAnimTable, sub_812A36C }; const struct YesNoFuncTable gUnknown_085A741C = { .yesFunc = sub_812A478, .noFunc = sub_8127A30, }; void InitDecorationContextItems(void) { if (sCurDecorationCategory < DECORCAT_COUNT) gCurDecorationItems = gDecorationInventories[sCurDecorationCategory].items; if (gDecorationContext.isPlayerRoom == FALSE) { gDecorationContext.items = gSaveBlock1Ptr->secretBases[0].decorations; gDecorationContext.pos = gSaveBlock1Ptr->secretBases[0].decorationPositions; } if (gDecorationContext.isPlayerRoom == TRUE) { gDecorationContext.items = gSaveBlock1Ptr->playerRoomDecor; gDecorationContext.pos = gSaveBlock1Ptr->playerRoomDecorPos; } } static u8 AddDecorationWindow(u8 windowIndex) { u8 *windowId; struct WindowTemplate template; windowId = &sDecorMenuWindowIds[windowIndex]; if (windowIndex == 0) { template = sDecorationWindowTemplates[0]; 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); schedule_bg_copy_tilemap_to_vram(0); return *windowId; } static void RemoveDecorationWindow(u8 windowIndex) { ClearStdWindowAndFrameToTransparent(sDecorMenuWindowIds[windowIndex], FALSE); ClearWindowTilemap(sDecorMenuWindowIds[windowIndex]); RemoveWindow(sDecorMenuWindowIds[windowIndex]); schedule_bg_copy_tilemap_to_vram(0); } static void AddDecorationActionsWindow(void) { u8 windowId = AddDecorationWindow(0); PrintMenuTable(windowId, 4, sDecorationMainMenuActions); InitMenuInUpperLeftCornerPlaySoundWhenAPressed(windowId, 4, sDecorationActionsCursorPos); } static void InitDecorationActionsWindow(void) { sDecorationActionsCursorPos = 0; ScriptContext2_Enable(); AddDecorationActionsWindow(); PrintCurMainMenuDescription(); } void DoSecretBaseDecorationMenu(u8 taskId) { InitDecorationActionsWindow(); gDecorationContext.items = gSaveBlock1Ptr->secretBases[0].decorations; gDecorationContext.pos = gSaveBlock1Ptr->secretBases[0].decorationPositions; gDecorationContext.size = sizeof(gSaveBlock1Ptr->secretBases[0].decorations); gDecorationContext.isPlayerRoom = FALSE; gTasks[taskId].func = HandleDecorationActionsMenuInput; } void DoPlayerRoomDecorationMenu(u8 taskId) { InitDecorationActionsWindow(); gDecorationContext.items = gSaveBlock1Ptr->playerRoomDecor; gDecorationContext.pos = gSaveBlock1Ptr->playerRoomDecorPos; gDecorationContext.size = sizeof(gSaveBlock1Ptr->playerRoomDecor); gDecorationContext.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].data[11] = 0; sCurDecorationCategory = DECORCAT_DESK; SecretBasePC_PrepMenuForSelectingStoredDecors(taskId); } } static void DecorationMenuAction_PutAway(u8 taskId) { if (!sub_81299AC(taskId)) { StringExpandPlaceholders(gStringVar4, gText_NoDecorationsInUse); DisplayItemMessageOnField(taskId, gStringVar4, ReturnToDecorationActionsAfterInvalidSelection); } else { RemoveDecorationWindow(0); ClearDialogWindowAndFrame(0, 0); FadeScreen(1, 0); gTasks[taskId].data[2] = 0; gTasks[taskId].func = sub_8129ABC; } } static void DecorationMenuAction_Toss(u8 taskId) { if (GetNumOwnedDecorations() == 0) { StringExpandPlaceholders(gStringVar4, gText_NoDecorations); DisplayItemMessageOnField(taskId, gStringVar4, ReturnToDecorationActionsAfterInvalidSelection); } else { gTasks[taskId].data[11] = 1; sCurDecorationCategory = DECORCAT_DESK; SecretBasePC_PrepMenuForSelectingStoredDecors(taskId); } } static void DecorationMenuAction_Cancel(u8 taskId) { RemoveDecorationWindow(0); if (!gDecorationContext.isPlayerRoom) { ScriptContext1_SetupScript(gUnknown_0823B4E8); 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(0); InitDecorationCategoriesWindow(taskId); } static void InitDecorationCategoriesWindow(u8 taskId) { u8 windowId = AddDecorationWindow(1); PrintDecorationCategoryMenuItems(taskId); InitMenuInUpperLeftCornerPlaySoundWhenAPressed(windowId, DECORCAT_COUNT + 1, sCurDecorationCategory); gTasks[taskId].func = HandleDecorationCategoriesMenuInput; } static void sub_8126E44(u8 taskId) { FillWindowPixelBuffer(sDecorMenuWindowIds[1], PIXEL_FILL(1)); PrintDecorationCategoryMenuItems(taskId); InitMenuInUpperLeftCornerPlaySoundWhenAPressed(sDecorMenuWindowIds[1], DECORCAT_COUNT + 1, sCurDecorationCategory); gTasks[taskId].func = HandleDecorationCategoriesMenuInput; } static void PrintDecorationCategoryMenuItems(u8 taskId) { u8 i; s16 *data = gTasks[taskId].data; u8 windowId = sDecorMenuWindowIds[1]; bool8 isPlayerRoom = gDecorationContext.isPlayerRoom; bool8 shouldDisable = FALSE; if (isPlayerRoom == TRUE && data[11] == 0) 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].data[11] == 2 ? gText_Exit : gText_Cancel, 8, i * 16 + 1, 0, NULL); schedule_bg_copy_tilemap_to_vram(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(1); 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].data[11] != 2) ReturnToActionsMenuFromCategories(taskId); else ExitTraderDecorationMenu(taskId); } static void ReturnToActionsMenuFromCategories(u8 taskId) { RemoveDecorationWindow(1); AddDecorationActionsWindow(); DrawDialogueFrame(0, 0); PrintCurMainMenuDescription(); gTasks[taskId].func = HandleDecorationActionsMenuInput; } void ShowDecorationCategoriesWindow(u8 taskId) { LoadPalette(sDecorationMenuPalette, 0xd0, 0x20); ClearDialogWindowAndFrame(0, 0); gTasks[taskId].data[11] = 2; sCurDecorationCategory = DECORCAT_DESK; InitDecorationCategoriesWindow(taskId); } void CopyDecorationCategoryName(u8 *dest, u8 category) { StringCopy(dest, sDecorationCategoryNames[category]); } static void ExitTraderDecorationMenu(u8 taskId) { RemoveDecorationWindow(1); ExitTraderMenu(taskId); } static void InitDecorationItemsMenuLimits(void) { sDecorationItemsMenu->numMenuItems = sNumOwnedDecorationsInCurCategory + 1; if (sDecorationItemsMenu->numMenuItems > 8) sDecorationItemsMenu->maxShownItems = 8; else sDecorationItemsMenu->maxShownItems = sDecorationItemsMenu->numMenuItems; } static void sub_81272C8(void) { sub_812225C(&sDecorationsScrollOffset, &sDecorationsCursorPos, sDecorationItemsMenu->maxShownItems, sDecorationItemsMenu->numMenuItems); } static void sub_81272F8(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) && gDecorationContext.isPlayerRoom == TRUE && data[11] == 0) 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[1]; 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); } void sub_81274A0(u8 a0, s32 a1, u8 a2) { if (a1 != -2) { if (sub_81277BC(a1 + 1) == TRUE) { blit_move_info_icon(a0, 0x18, 0x5c, a2 + 2); } else if (sub_81277E8(a1 + 1) == TRUE) { blit_move_info_icon(a0, 0x19, 0x5c, a2 + 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; } } void sub_8127580(u8 taskId) { AddDecorationWindow(1); InitDecorationItemsWindow(taskId); } static void InitDecorationItemsWindow(u8 taskId) { s16 *data = gTasks[taskId].data; AddDecorationWindow(3); ShowDecorationCategorySummaryWindow(sCurDecorationCategory); sDecorationItemsMenu = AllocZeroed(sizeof(*sDecorationItemsMenu)); sDecorationItemsMenu->scrollIndicatorsTaskId = 0xFF; InitDecorationItemsMenuLimits(); sub_81272C8(); sub_81272F8(); PrintDecorationItemMenuItems(taskId); data[13] = 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(data[13]); ListMenuGetScrollAndRow(data[13], &sDecorationsScrollOffset, &sDecorationsCursorPos); switch (input) { case LIST_NOTHING_CHOSEN: break; case LIST_CANCEL: PlaySE(SE_SELECT); sSecretBasePC_SelectedDecorationActions[data[11]][1](taskId); break; default: PlaySE(SE_SELECT); gCurDecorationIndex = input; RemoveDecorationItemsScrollIndicators(); DestroyListMenuTask(data[13], &sDecorationsScrollOffset, &sDecorationsCursorPos); RemoveDecorationWindow(1); RemoveDecorationItemsOtherWindows(); free(sDecorationItemsMenu); sSecretBasePC_SelectedDecorationActions[data[11]][0](taskId); break; } } } static void ShowDecorationCategorySummaryWindow(u8 category) { PrintDecorationCategoryMenuItem(AddDecorationWindow(2), category, 0, 0, 0, 0); } static void PrintDecorationItemDescription(u32 itemIndex) { u8 windowId; const u8 *str; windowId = sDecorMenuWindowIds[3]; FillWindowPixelBuffer(windowId, PIXEL_FILL(1)); if (itemIndex >= sNumOwnedDecorationsInCurCategory) str = gText_GoBackPrevMenu; else str = gDecorations[gCurDecorationItems[itemIndex]].description; AddTextPrinterParameterized(windowId, 1, str, 0, 1, 0, 0); } static void RemoveDecorationItemsOtherWindows(void) { // Remove description and category summary windows RemoveDecorationWindow(3); RemoveDecorationWindow(2); } bool8 sub_81277BC(u8 idx) { u8 i; for (i = 0; i < ARRAY_COUNT(sSecretBaseItemsIndicesBuffer); i++) { if (sSecretBaseItemsIndicesBuffer[i] == idx) return TRUE; } return FALSE; } bool8 sub_81277E8(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->playerRoomDecor[i] != DECOR_NONE) { for (j = 0; j < gDecorationInventories[sCurDecorationCategory].size; j++) { if (gCurDecorationItems[j] == gSaveBlock1Ptr->playerRoomDecor[i] && sub_81277BC(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 sub_8127A14(u8 taskId) { AddDecorationWindow(1); ShowDecorationItemsWindow(taskId); } void sub_8127A30(u8 taskId) { ClearDialogWindowAndFrame(0, 0); gTasks[taskId].func = sub_8127A14; } void sub_8127A5C(u8 taskId) { if (gMain.newKeys & (A_BUTTON | B_BUTTON)) { ClearDialogWindowAndFrame(0, 0); AddDecorationWindow(1); ShowDecorationItemsWindow(taskId); } } void sub_8127A8C(u8 taskId) { s16 *data = gTasks[taskId].data; RemoveDecorationItemsScrollIndicators(); RemoveDecorationItemsOtherWindows(); DestroyListMenuTask(data[13], NULL, NULL); free(sDecorationItemsMenu); sub_8126E44(taskId); } void sub_8127ACC(u8 taskId) { gTasks[taskId].data[3] = gSaveBlock1Ptr->pos.x; gTasks[taskId].data[4] = gSaveBlock1Ptr->pos.y; PlayerGetDestCoords(&gTasks[taskId].data[0], &gTasks[taskId].data[1]); } void sub_8127B04(u8 taskId) { DrawWholeMapView(); SetWarpDestination(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1, gTasks[taskId].data[3], gTasks[taskId].data[4]); WarpIntoMap(); } static u16 GetDecorationElevation(u8 decoration, u8 tileIndex) { u16 elevation = -1; switch (decoration) { case DECOR_STAND: elevation = sDecorationStandElevations[tileIndex] << 12; return elevation; case DECOR_SLIDE: elevation = sDecorationSlideElevation[tileIndex] << 12; 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 posterSide; 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 >> 12))) impassableFlag = METATILE_COLLISION_MASK; else impassableFlag = 0; if (gDecorations[decoration].permission != DECORPERM_NA_WALL && MetatileBehavior_IsSecretBaseNorthWall(MapGridGetMetatileBehaviorAt(x, y)) == TRUE) posterSide = 1; else posterSide = 0; elevation = GetDecorationElevation(gDecorations[decoration].id, j * decWidth + i); if (elevation != 0xFFFF) MapGridSetMetatileEntryAt(x, y, (gDecorations[decoration].tiles[j * decWidth + i] + (0x200 | posterSide)) | impassableFlag | elevation); else MapGridSetMetatileIdAt(x, y, (gDecorations[decoration].tiles[j * decWidth + i] + (0x200 | posterSide)) | 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 sub_8127E18(void) { u8 i; u8 j; for (i = 0; i < 14; i++) { if (FlagGet(FLAG_DECORATION_1 + i) == TRUE) { FlagClear(FLAG_DECORATION_1 + i); for (j = 0; j < gMapHeader.events->eventObjectCount; j++) { if (gMapHeader.events->eventObjects[j].flagId == FLAG_DECORATION_1 + i) break; } VarSet( VAR_OBJ_GFX_ID_0 + (gMapHeader.events->eventObjects[j].graphicsId - EVENT_OBJ_GFX_VAR_0), sPlaceDecorationGraphicsDataBuffer.decoration->tiles[0]); gSpecialVar_0x8005 = gMapHeader.events->eventObjects[j].localId; gSpecialVar_0x8006 = sCurDecorMapX; gSpecialVar_0x8007 = sCurDecorMapY; TrySpawnEventObject(gSpecialVar_0x8005, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); TryMoveEventObjectToMapCoords(gSpecialVar_0x8005, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, gSpecialVar_0x8006, gSpecialVar_0x8007); TryOverrideEventObjectTemplateCoords(gSpecialVar_0x8005, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); break; } } } bool8 sub_8127F38(void) { u16 i; for (i = 0; i < gDecorationContext.size; i++) { if (gDecorationContext.items[i] == DECOR_NONE) { return TRUE; } } return FALSE; } void sub_8127F68(u8 taskId) { if (gDecorationContext.isPlayerRoom == TRUE && sCurDecorationCategory != DECORCAT_DOLL && sCurDecorationCategory != DECORCAT_CUSHION) { StringExpandPlaceholders(gStringVar4, gText_CantPlaceInRoom); DisplayItemMessageOnField(taskId, gStringVar4, sub_8127A5C); } else if (IsSelectedDecorInThePC() == TRUE) { if (sub_8127F38() == TRUE) { FadeScreen(1, 0); gTasks[taskId].data[2] = 0; gTasks[taskId].func = sub_8128060; } else { ConvertIntToDecimalStringN(gStringVar1, gDecorationContext.size, STR_CONV_MODE_RIGHT_ALIGN, 2); if (gDecorationContext.isPlayerRoom == FALSE) { StringExpandPlaceholders(gStringVar4, gText_NoMoreDecorations); } else { StringExpandPlaceholders(gStringVar4, gText_NoMoreDecorations2); } DisplayItemMessageOnField(taskId, gStringVar4, sub_8127A5C); } } else { StringExpandPlaceholders(gStringVar4, gText_InUseAlready); DisplayItemMessageOnField(taskId, gStringVar4, sub_8127A5C); } } void sub_8128060(u8 taskId) { switch (gTasks[taskId].data[2]) { case 0: if (!gPaletteFade.active) { sub_8127ACC(taskId); gTasks[taskId].data[2] = 1; } break; case 1: gPaletteFade.bufferTransferDisabled = TRUE; ConfigureCameraObjectForPlacingDecoration(&sPlaceDecorationGraphicsDataBuffer, gCurDecorationItems[gCurDecorationIndex]); sub_812826C(taskId); SetUpPlacingDecorationPlayerAvatar(taskId, &sPlaceDecorationGraphicsDataBuffer); pal_fill_black(); gPaletteFade.bufferTransferDisabled = FALSE; gTasks[taskId].data[2] = 2; break; case 2: if (IsWeatherNotFadingIn() == TRUE) { gTasks[taskId].data[12] = 0; sub_8128FD8(taskId); } break; } } 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 = sub_81292D0; gSprites[gFieldCamera.spriteId].pos1.x = sDecorationMovementInfo[data->decoration->shape].cameraX; gSprites[gFieldCamera.spriteId].pos1.y = sDecorationMovementInfo[data->decoration->shape].cameraY; } void SetUpPlacingDecorationPlayerAvatar(u8 taskId, struct PlaceDecorationGraphicsDataBuffer *data) { u8 x; x = 16 * (u8)gTasks[taskId].data[5] + sDecorationMovementInfo[data->decoration->shape].cameraX - 8 * ((u8)gTasks[taskId].data[5] - 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 = AddPseudoEventObject(EVENT_OBJ_GFX_BRENDAN_DECORATING, SpriteCallbackDummy, x, 72, 0); else sDecor_CameraSpriteObjectIdx2 = AddPseudoEventObject(EVENT_OBJ_GFX_MAY_DECORATING, SpriteCallbackDummy, x, 72, 0); gSprites[sDecor_CameraSpriteObjectIdx2].oam.priority = 1; DestroySprite(&gSprites[sDecor_CameraSpriteObjectIdx1]); sDecor_CameraSpriteObjectIdx1 = gFieldCamera.spriteId; } void sub_812826C(u8 taskId) { switch (gDecorations[gCurDecorationItems[gCurDecorationIndex]].shape) { case DECORSHAPE_1x1: gTasks[taskId].data[5] = 1; gTasks[taskId].data[6] = 1; break; case DECORSHAPE_2x1: gTasks[taskId].data[5] = 2; gTasks[taskId].data[6] = 1; break; case DECORSHAPE_3x1: gTasks[taskId].data[5] = 3; gTasks[taskId].data[6] = 1; break; case DECORSHAPE_4x2: gTasks[taskId].data[5] = 4; gTasks[taskId].data[6] = 2; break; case DECORSHAPE_2x2: gTasks[taskId].data[5] = 2; gTasks[taskId].data[6] = 2; break; case DECORSHAPE_1x2: gTasks[taskId].data[5] = 1; gTasks[taskId].data[6] = 2; break; case DECORSHAPE_1x3: gTasks[taskId].data[5] = 1; gTasks[taskId].data[6] = 3; gTasks[taskId].data[1]++; break; case DECORSHAPE_2x4: gTasks[taskId].data[5] = 2; gTasks[taskId].data[6] = 4; break; case DECORSHAPE_3x3: gTasks[taskId].data[5] = 3; gTasks[taskId].data[6] = 3; break; case DECORSHAPE_3x2: gTasks[taskId].data[5] = 3; gTasks[taskId].data[6] = 2; break; } } void sub_81283BC(u8 taskId) { gTasks[taskId].data[10] = 0; gSprites[sDecor_CameraSpriteObjectIdx1].data[7] = 1; gSprites[sDecor_CameraSpriteObjectIdx2].data[7] = 1; sub_8128DE0(); sub_8128950(taskId); } void sub_8128414(u8 taskId) { gTasks[taskId].data[10] = 0; gSprites[sDecor_CameraSpriteObjectIdx1].data[7] = 1; gSprites[sDecor_CameraSpriteObjectIdx2].data[7] = 1; sub_8128DE0(); StringExpandPlaceholders(gStringVar4, gText_CancelDecorating); DisplayItemMessageOnField(taskId, gStringVar4, sub_8128B80); } bool8 sub_8128484(u8 behaviorAt, u16 behaviorBy) { if (MetatileBehavior_IsBlockDecoration(behaviorAt) != TRUE || behaviorBy != 0) { return FALSE; } return TRUE; } bool8 sub_81284AC(u8 taskId, s16 x, s16 y, u16 decor) { if (x == gTasks[taskId].data[3] + 7 && y == gTasks[taskId].data[4] + 7 && decor != DECOR_NONE) { return FALSE; } return TRUE; } bool8 sub_81284F4(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; } bool8 sub_812853C(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].data[6]; mapX = gTasks[taskId].data[5]; switch (decoration->permission) { case DECORPERM_SOLID_FLOOR: case DECORPERM_PASS_FLOOR: for (i = 0; i < mapY; i++) { curY = gTasks[taskId].data[1] - i; for (j = 0; j < mapX; j++) { curX = gTasks[taskId].data[0] + j; behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY); behaviorBy = GetBehaviorByMetatileId(0x200 + decoration->tiles[(mapY - 1 - i) * mapX + j]) & METATILE_ELEVATION_MASK; if (!sub_81284F4(behaviorAt, decoration)) return FALSE; if (!sub_81284AC(taskId, curX, curY, behaviorBy)) return FALSE; behaviorAt = GetEventObjectIdByXYZ(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].data[1] - i; for (j = 0; j < mapX; j++) { curX = gTasks[taskId].data[0] + j; behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY); behaviorBy = GetBehaviorByMetatileId(0x200 + decoration->tiles[(mapY - 1 - i) * mapX + j]) & METATILE_ELEVATION_MASK; if (!MetatileBehavior_IsNormal(behaviorAt) && !sub_8128484(behaviorAt, behaviorBy)) return FALSE; if (!sub_81284AC(taskId, curX, curY, behaviorBy)) return FALSE; if (GetEventObjectIdByXYZ(curX, curY, 0) != 16) return FALSE; } } curY = gTasks[taskId].data[1] - mapY + 1; for (j = 0; j < mapX; j++) { curX = gTasks[taskId].data[0] + j; behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY); behaviorBy = GetBehaviorByMetatileId(0x200 + decoration->tiles[j]) & METATILE_ELEVATION_MASK; if (!MetatileBehavior_IsNormal(behaviorAt) && !MetatileBehavior_IsSecretBaseNorthWall(behaviorAt)) return FALSE; if (!sub_81284AC(taskId, curX, curY, behaviorBy)) return FALSE; behaviorAt = GetEventObjectIdByXYZ(curX, curY, 0); if (behaviorAt != 0 && behaviorAt != 16) return FALSE; } break; case DECORPERM_NA_WALL: for (i = 0; i < mapY; i++) { curY = gTasks[taskId].data[1] - i; for (j = 0; j < mapX; j++) { curX = gTasks[taskId].data[0] + j; if (!MetatileBehavior_IsSecretBaseNorthWall(MapGridGetMetatileBehaviorAt(curX, curY))) return FALSE; if (MapGridGetMetatileIdAt(curX, curY + 1) == 0x28c) return FALSE; } } break; case DECORPERM_SPRITE: curY = gTasks[taskId].data[1]; for (j = 0; j < mapX; j++) { curX = gTasks[taskId].data[0] + 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 (GetEventObjectIdByXYZ(curX, curY, 0) != 16) return FALSE; } break; } return TRUE; } void sub_8128950(u8 taskId) { if (sub_812853C(taskId, &gDecorations[gCurDecorationItems[gCurDecorationIndex]]) == TRUE) { StringExpandPlaceholders(gStringVar4, gText_PlaceItHere); DisplayItemMessageOnField(taskId, gStringVar4, sub_81289D0); } else { PlaySE(SE_HAZURE); StringExpandPlaceholders(gStringVar4, gText_CantBePlacedHere); DisplayItemMessageOnField(taskId, gStringVar4, sub_8129020); } } void sub_81289D0(u8 taskId) { DisplayYesNoMenuDefaultYes(); DoYesNoFuncWithChoice(taskId, &gUnknown_085A72C4); } void sub_81289F0(u8 taskId) { ClearDialogWindowAndFrame(0, 0); sub_8128AAC(taskId); if (gDecorations[gCurDecorationItems[gCurDecorationIndex]].permission != DECORPERM_SPRITE) { ShowDecorationOnMap(gTasks[taskId].data[0], gTasks[taskId].data[1], gCurDecorationItems[gCurDecorationIndex]); } else { sCurDecorMapX = gTasks[taskId].data[0] - 7; sCurDecorMapY = gTasks[taskId].data[1] - 7; ScriptContext1_SetupScript(EventScript_275D1F); } gSprites[sDecor_CameraSpriteObjectIdx1].pos1.y += 2; if (gMapHeader.regionMapSectionId == MAPSEC_SECRET_BASE) TV_PutSecretBaseVisitOnTheAir(); sub_8128BBC(taskId); } void sub_8128AAC(u8 taskId) { u16 i; for (i = 0; i < gDecorationContext.size; i++) { if (gDecorationContext.items[i] == DECOR_NONE) { gDecorationContext.items[i] = gCurDecorationItems[gCurDecorationIndex]; gDecorationContext.pos[i] = ((gTasks[taskId].data[0] - 7) << 4) + (gTasks[taskId].data[1] - 7); break; } } if (!gDecorationContext.isPlayerRoom) { for (i = 0; i < 16; i++) { if (sSecretBaseItemsIndicesBuffer[i] == 0) { sSecretBaseItemsIndicesBuffer[i] = gCurDecorationIndex + 1; break; } } } else { for (i = 0; i < 12; i++) { if (sPlayerRoomItemsIndicesBuffer[i] == 0) { sPlayerRoomItemsIndicesBuffer[i] = gCurDecorationIndex + 1; break; } } } } void sub_8128B80(u8 taskId) { DisplayYesNoMenuDefaultYes(); DoYesNoFuncWithChoice(taskId, &gUnknown_085A72CC); } void sub_8128BA0(u8 taskId) { ClearDialogWindowAndFrame(0, 0); sub_8128BBC(taskId); } void sub_8128BBC(u8 taskId) { FadeScreen(1, 0); gTasks[taskId].data[2] = 0; gTasks[taskId].func = c1_overworld_prev_quest; } void c1_overworld_prev_quest(u8 taskId) { switch (gTasks[taskId].data[2]) { case 0: ScriptContext2_Enable(); if (!gPaletteFade.active) { sub_8127B04(taskId); gTasks[taskId].data[2] = 1; } break; case 1: sub_812A3C8(); FreeSpritePaletteByTag(PLACE_DECORATION_SELECTOR_TAG); gFieldCallback = sub_8128CD4; SetMainCallback2(CB2_ReturnToField); DestroyTask(taskId); break; } } void sub_8128C64(u8 taskId) { s16 *data = gTasks[taskId].data; switch (data[2]) { case 0: HideSecretBaseDecorationSprites(); data[2]++; break; case 1: ScriptContext1_SetupScript(EventScript_275D0C); data[2]++; break; case 2: ScriptContext2_Enable(); data[2]++; break; case 3: if (IsWeatherNotFadingIn() == TRUE) gTasks[taskId].func = HandleDecorationItemsMenuInput; break; } } void sub_8128CD4(void) { u8 taskId; ScriptContext2_Enable(); pal_fill_black(); taskId = CreateTask(sub_8128C64, 8); sub_8127580(taskId); gTasks[taskId].data[2] = 0; } bool8 sub_8128D10(u8 taskId) { s16 *data = gTasks[taskId].data; if (sDecorationLastDirectionMoved == DIR_SOUTH && data[1] - data[6] - 6 < 0) { data[1]++; return FALSE; } if (sDecorationLastDirectionMoved == DIR_NORTH && data[1] - 7 >= gMapHeader.mapLayout->height) { data[1]--; return FALSE; } if (sDecorationLastDirectionMoved == DIR_WEST && data[0] - 7 < 0) { data[0]++; return FALSE; } if (sDecorationLastDirectionMoved == DIR_EAST && data[0] + data[5] - 8 >= gMapHeader.mapLayout->width) { data[0]--; return FALSE; } return TRUE; } bool8 sub_8128DB4(void) { u16 heldKeys = gMain.heldKeys & DPAD_ANY; if (heldKeys != DPAD_UP && heldKeys != DPAD_DOWN && heldKeys != DPAD_LEFT && heldKeys != DPAD_RIGHT) return FALSE; return TRUE; } void sub_8128DE0(void) { sDecorationLastDirectionMoved = 0; gSprites[sDecor_CameraSpriteObjectIdx1].data[2] = 0; gSprites[sDecor_CameraSpriteObjectIdx1].data[3] = 0; } void sub_8128E18(u8 taskId) { s16 *data = gTasks[taskId].data; if (!gSprites[sDecor_CameraSpriteObjectIdx1].data[4]) { if (data[10] == 1) { gUnknown_085A72D4[data[12]].yesFunc(taskId); return; } else if (data[10] == 2) { gUnknown_085A72D4[data[12]].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; data[1]--; } if ((gMain.heldKeys & DPAD_ANY) == DPAD_DOWN) { sDecorationLastDirectionMoved = DIR_NORTH; gSprites[sDecor_CameraSpriteObjectIdx1].data[2] = 0; gSprites[sDecor_CameraSpriteObjectIdx1].data[3] = 2; data[1]++; } if ((gMain.heldKeys & DPAD_ANY) == DPAD_LEFT) { sDecorationLastDirectionMoved = DIR_WEST; gSprites[sDecor_CameraSpriteObjectIdx1].data[2] = -2; gSprites[sDecor_CameraSpriteObjectIdx1].data[3] = 0; data[0]--; } if ((gMain.heldKeys & DPAD_ANY) == DPAD_RIGHT) { sDecorationLastDirectionMoved = DIR_EAST; gSprites[sDecor_CameraSpriteObjectIdx1].data[2] = 2; gSprites[sDecor_CameraSpriteObjectIdx1].data[3] = 0; data[0]++; } if (!sub_8128DB4() || !sub_8128D10(taskId)) sub_8128DE0(); } if (sDecorationLastDirectionMoved) { gSprites[sDecor_CameraSpriteObjectIdx1].data[4]++; gSprites[sDecor_CameraSpriteObjectIdx1].data[4] &= 7; } if (!data[10]) { if (gMain.newKeys & A_BUTTON) data[10] = A_BUTTON; if (gMain.newKeys & B_BUTTON) data[10] = B_BUTTON; } } void sub_8128FD8(u8 taskId) { ClearDialogWindowAndFrame(0, 1); gSprites[sDecor_CameraSpriteObjectIdx1].data[7] = 0; gTasks[taskId].data[10] = 0; gTasks[taskId].func = sub_8128E18; } void sub_8129020(u8 taskId) { if (gMain.newKeys & A_BUTTON || gMain.newKeys & B_BUTTON) sub_8128FD8(taskId); } void sub_8129048(struct PlaceDecorationGraphicsDataBuffer *data) { CpuFill16(0, data, sizeof(*data)); } void sub_8129068(u16 *dest, u16 pal) { CpuFastCopy(&((u16 *)gTilesetPointer_SecretBase->palettes)[pal << 4], dest, 32); } void sub_8129088(u8 *dest, u16 tile) { u8 buffer[32]; u16 mode; u16 i; mode = tile >> 10; if (tile != 0) tile &= 0x03FF; CpuFastCopy(&((u8 *)gTilesetPointer_SecretBase->tiles)[tile << 5], buffer, 32); switch (mode) { case 0: CpuFastCopy(buffer, dest, 32); break; case 1: 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 2: 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 3: for (i = 0; i < 32; i++) { dest[i] = (buffer[31 - i] >> 4) + ((buffer[31 - i] & 0x0F) << 4); } break; } } void sub_81291A4(struct PlaceDecorationGraphicsDataBuffer *data) { u16 i; for (i = 0; i < 64; i++) sub_8129088(&data->image[i * 32], data->tiles[i]); } u16 sub_81291CC(u16 tile) { return ((u16 *)gTilesetPointer_SecretBaseRedCave->metatiles)[tile] & 0xFFF; } void sub_81291E8(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]] = sub_81291CC(data->decoration->tiles[gUnknown_085A71B0[shape].y[i]] * 8 + gUnknown_085A71B0[shape].x[i]); } } 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; } void sub_81292D0(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 = sub_81292E8; } void sub_81292E8(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; } } u8 gpu_pal_decompress_alloc_tag_and_upload(struct PlaceDecorationGraphicsDataBuffer *data, u8 decor) { sub_8129048(data); data->decoration = &gDecorations[decor]; if (data->decoration->permission == DECORPERM_SPRITE) return AddPseudoEventObject(data->decoration->tiles[0], SpriteCallbackDummy, 0, 0, 1); FreeSpritePaletteByTag(PLACE_DECORATION_SELECTOR_TAG); sub_81291E8(data); SetDecorSelectionBoxOamAttributes(data->decoration->shape); sub_81291A4(data); sub_8129068(data->palette, ((u16 *)gTilesetPointer_SecretBaseRedCave->metatiles)[(data->decoration->tiles[0] * 8) + 7] >> 12); LoadSpritePalette(&gUnknown_085A72BC); return CreateSprite(&sDecorationSelectorSpriteTemplate, 0, 0, 0); } 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; } const u32 *GetDecorationIconPicOrPalette(u16 decor, u8 mode) { if (decor > NUM_DECORATIONS) decor = DECOR_NONE; return gUnknown_085A6BE8[decor][mode]; } u8 AddDecorationIconObjectFromEventObject(u16 tilesTag, u16 paletteTag, u8 decor) { u8 spriteId; struct SpriteSheet sheet; struct SpritePalette palette; struct SpriteTemplate *template; sub_8129048(&sPlaceDecorationGraphicsDataBuffer); sPlaceDecorationGraphicsDataBuffer.decoration = &gDecorations[decor]; if (sPlaceDecorationGraphicsDataBuffer.decoration->permission != DECORPERM_SPRITE) { sub_81291E8(&sPlaceDecorationGraphicsDataBuffer); SetDecorSelectionBoxOamAttributes(sPlaceDecorationGraphicsDataBuffer.decoration->shape); sub_81291A4(&sPlaceDecorationGraphicsDataBuffer); sub_8129068(sPlaceDecorationGraphicsDataBuffer.palette, ((u16 *)gTilesetPointer_SecretBaseRedCave->metatiles)[(sPlaceDecorationGraphicsDataBuffer.decoration->tiles[0] * 8) + 7] >> 12); sheet.data = sPlaceDecorationGraphicsDataBuffer.image; sheet.size = gUnknown_085A72F4[sPlaceDecorationGraphicsDataBuffer.decoration->shape] << 5; 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 = AddPseudoEventObject(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 (gUnknown_085A6BE8[decor][0] == NULL) { spriteId = AddDecorationIconObjectFromEventObject(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; } void sub_81296EC(u8 idx) { gDecorationContext.items[idx] = 0; gDecorationContext.pos[idx] = 0; } void sub_8129708(void) { u16 i; gSpecialVar_0x8005 = 0; gSpecialVar_Result = 0; if (gSpecialVar_0x8004 == sCurDecorSelectedInRearrangement) { gSpecialVar_Result = 1; } else if (gDecorations[gDecorationContext.items[sDecorRearrangementDataBuffer[gSpecialVar_0x8004].idx]].permission == DECORPERM_SPRITE) { gSpecialVar_0x8005 = sDecorRearrangementDataBuffer[gSpecialVar_0x8004].flagId; sub_81296EC(sDecorRearrangementDataBuffer[gSpecialVar_0x8004].idx); for (i = 0; i < gMapHeader.events->eventObjectCount; i++) { if (gMapHeader.events->eventObjects[i].flagId == gSpecialVar_0x8005) { gSpecialVar_0x8006 = gMapHeader.events->eventObjects[i].localId; break; } } } } void sub_81297AC(void) { u8 i; for (i = 0; i < gMapHeader.events->eventObjectCount; i++) { if (gMapHeader.events->eventObjects[i].flagId == gSpecialVar_0x8004) { gSpecialVar_0x8005 = gMapHeader.events->eventObjects[i].localId; break; } } } void sub_81297F8(void) { u8 i; u8 y; u8 x; int posX; int posY; u8 perm; for (i = 0; i < sCurDecorSelectedInRearrangement; i++) { perm = gDecorations[gDecorationContext.items[sDecorRearrangementDataBuffer[i].idx]].permission; posX = gDecorationContext.pos[sDecorRearrangementDataBuffer[i].idx] >> 4; posY = gDecorationContext.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); } } sub_81296EC(sDecorRearrangementDataBuffer[i].idx); } } } void sub_81298EC(u8 taskId) { switch (gTasks[taskId].data[2]) { case 0: sub_81297F8(); gTasks[taskId].data[2] = 1; break; case 1: if (!gPaletteFade.active) { DrawWholeMapView(); ScriptContext1_SetupScript(EventScript_275D2E); ClearDialogWindowAndFrame(0, 1); gTasks[taskId].data[2] = 2; } break; case 2: ScriptContext2_Enable(); IdentifyOwnedDecorationsCurrentlyInUseInternal(taskId); pal_fill_black(); gTasks[taskId].data[2] = 3; break; case 3: if (IsWeatherNotFadingIn() == TRUE) { StringExpandPlaceholders(gStringVar4, gText_DecorationReturnedToPC); DisplayItemMessageOnField(taskId, gStringVar4, sub_8129D64); if (gMapHeader.regionMapSectionId == MAPSEC_SECRET_BASE) TV_PutSecretBaseVisitOnTheAir(); } break; } } bool8 sub_81299AC(u8 taskId) { u16 i; for (i = 0; i < gDecorationContext.size; i++) { if (gDecorationContext.items[i] != DECOR_NONE) return TRUE; } return FALSE; } void SetUpPuttingAwayDecorationPlayerAvatar(void) { GetPlayerFacingDirection(); sDecor_CameraSpriteObjectIdx1 = gSprites[gFieldCamera.spriteId].data[0]; sub_812A39C(); gFieldCamera.spriteId = CreateSprite(&gUnknown_085A7404, 120, 80, 0); if (gSaveBlock2Ptr->playerGender == MALE) sDecor_CameraSpriteObjectIdx2 = AddPseudoEventObject(EVENT_OBJ_GFX_BRENDAN_DECORATING, SpriteCallbackDummy, 136, 72, 0); else sDecor_CameraSpriteObjectIdx2 = AddPseudoEventObject(EVENT_OBJ_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; } void sub_8129ABC(u8 taskId) { s16 *data; data = gTasks[taskId].data; switch (data[2]) { case 0: if (!gPaletteFade.active) { sub_8127ACC(taskId); data[2] = 1; data[6] = 1; data[5] = 1; } break; case 1: SetUpPuttingAwayDecorationPlayerAvatar(); pal_fill_black(); data[2] = 2; break; case 2: if (IsWeatherNotFadingIn() == TRUE) { data[12] = 1; sub_8129B34(taskId); } break; } } void sub_8129B34(u8 taskId) { ClearDialogWindowAndFrame(0, 1); gSprites[sDecor_CameraSpriteObjectIdx1].data[7] = 0; gSprites[sDecor_CameraSpriteObjectIdx1].invisible = FALSE; gSprites[sDecor_CameraSpriteObjectIdx1].callback = sub_812A36C; gSprites[sDecor_CameraSpriteObjectIdx2].pos1.x = 136; gSprites[sDecor_CameraSpriteObjectIdx2].pos1.y = 72; gTasks[taskId].data[10] = 0; gTasks[taskId].func = sub_8128E18; } void sub_8129BCC(u8 taskId) { gTasks[taskId].data[10] = 0; sub_8128DE0(); sub_8129C74(taskId); } void sub_8129BF8(u8 taskId) { gTasks[taskId].data[10] = 0; sub_8128DE0(); gSprites[sDecor_CameraSpriteObjectIdx1].invisible = FALSE; gSprites[sDecor_CameraSpriteObjectIdx1].callback = SpriteCallbackDummy; StringExpandPlaceholders(gStringVar4, gText_StopPuttingAwayDecorations); DisplayItemMessageOnField(taskId, gStringVar4, sub_812A1F0); } void sub_8129C74(u8 taskId) { s16 *data; u8 behavior; sub_812A0E8(taskId); if (sCurDecorSelectedInRearrangement != 0) { StringExpandPlaceholders(gStringVar4, gText_ReturnDecorationToPC); DisplayItemMessageOnField(taskId, gStringVar4, sub_812A1A0); } else { data = gTasks[taskId].data; behavior = MapGridGetMetatileBehaviorAt(data[0], data[1]); 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, sub_812A1F0); } else { StringExpandPlaceholders(gStringVar4, gText_NoDecorationHere); DisplayItemMessageOnField(taskId, gStringVar4, sub_8129D64); } } } void sub_8129D64(u8 taskId) { if (gMain.newKeys & A_BUTTON || gMain.newKeys & B_BUTTON) sub_8129B34(taskId); } void sub_8129D8C(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; } } void sub_8129E0C(u8 x, u8 y) { gSprites[sDecor_CameraSpriteObjectIdx1].invisible = TRUE; gSprites[sDecor_CameraSpriteObjectIdx1].callback = SpriteCallbackDummy; gSprites[sDecor_CameraSpriteObjectIdx2].pos1.x = (x << 4) + 136; gSprites[sDecor_CameraSpriteObjectIdx2].pos1.y = (y << 4) + 72; } bool8 sub_8129E74(u8 taskId, u8 idx, struct DecorRearrangementDataBuffer *data) { u8 x; u8 y; u8 xOff; u8 yOff; u8 ht; x = gTasks[taskId].data[0] - 7; y = gTasks[taskId].data[1] - 7; xOff = gDecorationContext.pos[idx] >> 4; yOff = gDecorationContext.pos[idx] & 0x0F; ht = data->height; if (gDecorationContext.items[idx] == DECOR_SAND_ORNAMENT && MapGridGetMetatileIdAt(xOff + 7, yOff + 7) == 0x28C) ht--; if (x >= xOff && x < xOff + data->width && y > yOff - ht && y <= yOff) { sub_8129E0C(data->width - (x - xOff + 1), yOff - y); return TRUE; } return FALSE; } void sub_8129F20(void) { u8 xOff; u8 yOff; u16 i; xOff = gDecorationContext.pos[sDecorRearrangementDataBuffer[sCurDecorSelectedInRearrangement].idx] >> 4; yOff = gDecorationContext.pos[sDecorRearrangementDataBuffer[sCurDecorSelectedInRearrangement].idx] & 0x0F; for (i = 0; i < 0x40; i++) { if (gSaveBlock1Ptr->eventObjectTemplates[i].x == xOff && gSaveBlock1Ptr->eventObjectTemplates[i].y == yOff && !FlagGet(gSaveBlock1Ptr->eventObjectTemplates[i].flagId)) { sDecorRearrangementDataBuffer[sCurDecorSelectedInRearrangement].flagId = gSaveBlock1Ptr->eventObjectTemplates[i].flagId; break; } } } bool8 sub_8129FC8(u8 taskId) { u16 i; for (i = 0; i < gDecorationContext.size; i++) { if (gDecorationContext.items[i] != 0) { if (gDecorations[gDecorationContext.items[i]].permission == DECORPERM_SPRITE) { sub_8129D8C(gDecorationContext.items[i], sDecorRearrangementDataBuffer); if (sub_8129E74(taskId, i, sDecorRearrangementDataBuffer) == TRUE) { sDecorRearrangementDataBuffer->idx = i; sub_8129F20(); sCurDecorSelectedInRearrangement = 1; return TRUE; } } } } return FALSE; } void sub_812A040(u8 left, u8 top, u8 right, u8 bottom) { u8 i; u8 xOff; u8 yOff; u8 decorIdx; for (i = 0; i < gDecorationContext.size; i++) { decorIdx = gDecorationContext.items[i]; xOff = gDecorationContext.pos[i] >> 4; yOff = gDecorationContext.pos[i] & 0x0F; if (decorIdx != 0 && gDecorations[decorIdx].permission == DECORPERM_SPRITE && left <= xOff && top <= yOff && right >= xOff && bottom >= yOff) { sDecorRearrangementDataBuffer[sCurDecorSelectedInRearrangement].idx = i; sub_8129F20(); sCurDecorSelectedInRearrangement++; } } } void sub_812A0E8(u8 taskId) { u8 i; u8 xOff; u8 yOff; u8 var1; u32 var2; sCurDecorSelectedInRearrangement = 0; if (sub_8129FC8(taskId) != TRUE) { for (i = 0; i < gDecorationContext.size; i++) { var1 = gDecorationContext.items[i]; if (var1 != DECOR_NONE) { sub_8129D8C(var1, &sDecorRearrangementDataBuffer[0]); if (sub_8129E74(taskId, i, &sDecorRearrangementDataBuffer[0]) == TRUE) { sDecorRearrangementDataBuffer[0].idx = i; sCurDecorSelectedInRearrangement++; break; } } } if (sCurDecorSelectedInRearrangement != 0) { xOff = gDecorationContext.pos[sDecorRearrangementDataBuffer[0].idx] >> 4; yOff = gDecorationContext.pos[sDecorRearrangementDataBuffer[0].idx] & 0x0F; var1 = yOff - sDecorRearrangementDataBuffer[0].height + 1; var2 = sDecorRearrangementDataBuffer[0].width + xOff - 1; sub_812A040(xOff, var1, var2, yOff); } } } void sub_812A1A0(u8 taskId) { DisplayYesNoMenuDefaultYes(); DoYesNoFuncWithChoice(taskId, &gUnknown_085A7348); } void sub_812A1C0(u8 taskId) { FadeScreen(1, 0); gTasks[taskId].data[2] = 0; gTasks[taskId].func = sub_81298EC; } void sub_812A1F0(u8 taskId) { DisplayYesNoMenuDefaultYes(); DoYesNoFuncWithChoice(taskId, &gUnknown_085A7350); } void sub_812A210(u8 taskId) { ClearDialogWindowAndFrame(0, 0); sub_812A22C(taskId); } void sub_812A22C(u8 taskId) { FadeScreen(1, 0); gTasks[taskId].data[2] = 0; gTasks[taskId].func = sub_812A25C; } void sub_812A25C(u8 taskId) { switch (gTasks[taskId].data[2]) { case 0: if (!gPaletteFade.active) { sub_8127B04(taskId); gTasks[taskId].data[2] = 1; } break; case 1: sub_812A3C8(); gFieldCallback = sub_812A334; SetMainCallback2(CB2_ReturnToField); DestroyTask(taskId); break; } } void sub_812A2C4(u8 taskId) { s16 *data = gTasks[taskId].data; switch (data[2]) { case 0: HideSecretBaseDecorationSprites(); data[2]++; break; case 1: ScriptContext1_SetupScript(EventScript_275D0C); data[2]++; break; case 2: ScriptContext2_Enable(); data[2]++; break; case 3: if (IsWeatherNotFadingIn() == TRUE) gTasks[taskId].func = HandleDecorationActionsMenuInput; break; } } void sub_812A334(void) { u8 taskId; pal_fill_black(); DrawDialogueFrame(0, 1); InitDecorationActionsWindow(); taskId = CreateTask(sub_812A2C4, 8); gTasks[taskId].data[2] = 0; } void sub_812A36C(struct Sprite *sprite) { sprite->data[0]++; sprite->data[0] &= 0x1F; if (sprite->data[0] > 15) sprite->invisible = TRUE; else sprite->invisible = FALSE; } void sub_812A39C(void) { if (gSaveBlock2Ptr->playerGender == MALE) LoadSpritePalette(&gUnknown_085A73D8); else LoadSpritePalette(&gUnknown_085A73E0); } void sub_812A3C8(void) { FreeSpritePaletteByTag(PLACE_DECORATION_PLAYER_TAG); } void sub_812A3D4(u8 taskId) { if (IsSelectedDecorInThePC() == TRUE) { StringCopy(gStringVar1, gDecorations[gCurDecorationItems[gCurDecorationIndex]].name); StringExpandPlaceholders(gStringVar4, gText_DecorationWillBeDiscarded); DisplayItemMessageOnField(taskId, gStringVar4, sub_812A458); } else { StringExpandPlaceholders(gStringVar4, gText_CantThrowAwayInUse); DisplayItemMessageOnField(taskId, gStringVar4, sub_8127A5C); } } void sub_812A458(u8 taskId) { DisplayYesNoMenuDefaultYes(); DoYesNoFuncWithChoice(taskId, &gUnknown_085A741C); } void sub_812A478(u8 taskId) { gCurDecorationItems[gCurDecorationIndex] = DECOR_NONE; sNumOwnedDecorationsInCurCategory = GetNumOwnedDecorationsInCategory(sCurDecorationCategory); CondenseDecorationsInCategory(sCurDecorationCategory); IdentifyOwnedDecorationsCurrentlyInUseInternal(taskId); StringExpandPlaceholders(gStringVar4, gText_DecorationThrownAway); DisplayItemMessageOnField(taskId, gStringVar4, sub_8127A5C); }