#include "ac_shop_level.h" #include "m_common_data.h" #include "m_player_lib.h" #include "m_house.h" #include "m_handbill.h" #include "m_string.h" static void Shop_Level_Actor_ct(ACTOR* actorx, GAME* game); static void Shop_Level_Actor_dt(ACTOR* actorx, GAME* game); static void Shop_Level_Actor_move(ACTOR* actorx, GAME* game); static void Shop_Level_Actor_draw(ACTOR* actorx, GAME* game); // clang-format off ACTOR_PROFILE Shop_Level_Profile = { mAc_PROFILE_SHOP_LEVEL, ACTOR_PART_CONTROL, ACTOR_STATE_CAN_MOVE_IN_DEMO_SCENES | ACTOR_STATE_NO_DRAW_WHILE_CULLED | ACTOR_STATE_NO_MOVE_WHILE_CULLED, EMPTY_NO, ACTOR_OBJ_BANK_KEEP, sizeof(SHOP_LEVEL_ACTOR), &Shop_Level_Actor_ct, &Shop_Level_Actor_dt, &Shop_Level_Actor_move, &Shop_Level_Actor_draw, NULL, }; // clang-format on static void aSL_SetShopRenewalChirashi_Notice(int shop_level, lbRTC_time_c* time_p) { static int renewal_chirashi_bunmen[] = { 0x0018, 0x0019, 0x001A, 0x001A }; int header_back_start; Mail_c mail; Mail_ct_c* content = &mail.content; u8 year_str[6]; u8 month_str[9]; u8 day_str[4]; lbRTC_time_c renew_start_date = *time_p; int i; lbRTC_Sub_DD(&renew_start_date, 1); for (i = 0; i < PLAYER_NUM; i++) { int player_no = mHS_get_pl_no_detail(i); int free_idx = mMl_chk_mail_free_space(Save_Get(homes[i]).mailbox, HOME_MAILBOX_SIZE); if (free_idx >= 0 && player_no != -1 && mEv_ArbeitPlayer(player_no) == FALSE) { int year_str_len; mString_Load_StringFromRom(month_str, sizeof(month_str), mString_MONTH_START + (renew_start_date.month - 1)); mHandbill_Set_free_str(mHandbill_FREE_STR0, month_str, sizeof(month_str)); mString_Load_StringFromRom(day_str, sizeof(day_str), mString_DAY_START + (renew_start_date.day - 1)); mHandbill_Set_free_str(mHandbill_FREE_STR1, day_str, sizeof(day_str)); year_str_len = mString_Load_YearStringFromRom(year_str, renew_start_date.year); mHandbill_Set_free_str(mHandbill_FREE_STR2, year_str, year_str_len); mMl_clear_mail(&mail); mHandbill_Load_HandbillFromRom(content->header, &header_back_start, content->footer, content->body, renewal_chirashi_bunmen[shop_level & 3]); content->header_back_start = header_back_start; content->font = mMl_FONT_0; content->paper_type = (u8)ITM_PAPER55; content->mail_type = mMl_TYPE_SHOP_SALE_LEAFLET; mPr_CopyPersonalID(&mail.header.recipient.personalID, &Save_Get(private_data[player_no]).player_ID); mail.header.recipient.type = mMl_NAME_TYPE_PLAYER; mMl_copy_mail(&Save_Get(homes[i]).mailbox[free_idx], &mail); } } } static void aSL_SetRenewalChiraswhi_Notice(void) { if (Save_Get(shop).shop_info.send_upgrade_notice == TRUE) { if (mSP_GetShopLevel() < mSP_GetRealShopLevel()) { lbRTC_time_c* rtc_time_p = Common_GetPointer(time.rtc_time); lbRTC_time_c renew_time = Save_Get(shop).renewal_time; lbRTC_Sub_DD(&renew_time, 1); if (lbRTC_IsOverTime(&renew_time, rtc_time_p) == lbRTC_OVER || lbRTC_IsEqualTime(rtc_time_p, &renew_time, lbRTC_CHECK_YEARS | lbRTC_CHECK_MONTHS | lbRTC_CHECK_DAYS)) { aSL_SetShopRenewalChirashi_Notice(mSP_GetShopLevel(), &Save_Get(shop).renewal_time); Save_Get(shop).shop_info.send_upgrade_notice = FALSE; } } else { aSL_SetShopRenewalChirashi_Notice((mSP_GetShopLevel() - 1) & 3, &Save_Get(shop).renewal_time); Save_Get(shop).shop_info.send_upgrade_notice = FALSE; } } } typedef struct shop_level_rewrite_offset_s { int ofs_ux; int ofs_uz; } aSL_rewrite_ofs_c; // clang-format off static aSL_rewrite_ofs_c aSL_zakka_rw[] = { { -1, -1 }, { 0, -1 }, { -2, 0 }, { -1, 0 }, { 1, 0 }, { -2, 1 }, { -1, 1 }, { 0, 1 }, { 1, 1 }, { -1, 2 }, { 0, 2 }, }; // clang-format on // clang-format off static aSL_rewrite_ofs_c aSL_conveni_rw[] = { { -2, -2 }, { -1, -2 }, { -3, -1 }, { -2, -1 }, { -1, -1 }, { 0, -1 }, { -3, 0 }, { -2, 0 }, { -1, 0 }, { 1, 0 }, { -2, 1 }, { -1, 1 }, { 0, 1 }, { 1, 1 }, { -1, 2 }, { 0, 2 }, }; // clang-format on // clang-format off static aSL_rewrite_ofs_c aSL_super_rw[] = { { -1, -3 }, { 0, -3 }, { -2, -2 }, { -1, -2 }, { 0, -2 }, { 1, -2 }, { -3, -1 }, { -2, -1 }, { -1, -1 }, { 0, -1 }, { 1, -1 }, { 2, -1 }, { -3, 0 }, { -2, 0 }, { -1, 0 }, { 1, 0 }, { 2, 0 }, { -2, 1 }, { -1, 1 }, { 0, 1 }, { 1, 1 }, { -1, 2 }, { 0, 2 }, }; // clang-format on static void aSL_GroundClean(s16 level, s16 next_level, mActor_name_t* fg_p, int bx, int bz, int ux, int uz) { static aSL_rewrite_ofs_c* table[] = { aSL_zakka_rw, aSL_conveni_rw, aSL_super_rw, aSL_super_rw, }; static int rw_cnt[] = { ARRAY_COUNT(aSL_zakka_rw), ARRAY_COUNT(aSL_conveni_rw), ARRAY_COUNT(aSL_super_rw), ARRAY_COUNT(aSL_super_rw), }; int i; aSL_rewrite_ofs_c* rewrite_ofs_p; u16* deposit_p; deposit_p = mFI_GetDepositP(bx, bz); rewrite_ofs_p = table[next_level & 3]; for (i = 0; i < rw_cnt[next_level & 3]; i++) { int rewrite_ux = (ux + rewrite_ofs_p[i].ofs_ux) & 0xF; int rewrite_uz = (uz + rewrite_ofs_p[i].ofs_uz) & 0xF; int rewrite_unit = rewrite_uz * UT_X_NUM + rewrite_ux; mPB_keep_item(fg_p[rewrite_unit]); mFI_BlockDepositOFF(deposit_p, rewrite_ux, rewrite_uz); fg_p[rewrite_unit] = RSV_NO; } } static int aSL_RewriteShopFg(ACTOR* actorx, GAME* game, s16 level, s16 next_level) { SHOP_LEVEL_ACTOR* shop_level = (SHOP_LEVEL_ACTOR*)actorx; int i; int ux; int uz; mActor_name_t* fg_top_p; mActor_name_t* fg_p; fg_top_p = mFI_BkNumtoUtFGTop(shop_level->bx, shop_level->bz); fg_p = fg_top_p; if (fg_top_p != NULL) { for (i = 0; i < UT_TOTAL_NUM; i++) { /* @BUG - shouldn't this just be <= SHOP3? This goes one over which would include the Post Office */ if (*fg_top_p >= SHOP0 && *fg_top_p <= (SHOP3 + 1)) { ux = i & 0xF; uz = (i >> 4) & 0xF; *fg_top_p = SHOP0 + next_level; aSL_GroundClean((s16)level, (s16)next_level, fg_p, shop_level->bx, shop_level->bz, ux, uz); return TRUE; } fg_top_p++; } } return FALSE; } static void aSL_RenewShop(ACTOR* actorx, GAME* game) { int last_scene = Common_Get(last_scene_no); if (last_scene == SCENE_SHOP0 || last_scene == SCENE_CONVENI || last_scene == SCENE_SUPER || last_scene == SCENE_DEPART || last_scene == SCENE_DEPART_2) { return; } if (mFI_GET_TYPE(mFI_GetFieldId()) == mFI_FIELD_FG && Save_Get(scene_no) == SCENE_FG && mEv_CheckEvent(mEv_SAVED_RENEWSHOP) == TRUE) { lbRTC_time_c renew_time = Save_Get(shop).renewal_time; lbRTC_time_c now_time = Common_Get(time.rtc_time); aSL_SetRenewalChiraswhi_Notice(); if (lbRTC_IsOverTime(&renew_time, &now_time) == lbRTC_OVER || lbRTC_IsEqualTime(&now_time, &renew_time, lbRTC_CHECK_YEARS | lbRTC_CHECK_MONTHS | lbRTC_CHECK_DAYS)) { if (aSL_RewriteShopFg(actorx, game, mSP_GetShopLevel(), mSP_GetRealShopLevel()) && mSP_RenewShopLevel()) { mEv_EventOFF(mEv_SAVED_RENEWSHOP); mSP_NewExchangeDay(); mSP_ExchangeLineUp_ZeldaMalloc(); } } } } static void Shop_Level_Actor_ct(ACTOR* actorx, GAME* game) { SHOP_LEVEL_ACTOR* shop_level = (SHOP_LEVEL_ACTOR*)actorx; GAME_PLAY* play = (GAME_PLAY*)game; ACTOR* player_actor = GET_PLAYER_ACTOR_ACTOR(play); xyz_t* pos_p; int shop_block_flag; shop_level->bx = 0; shop_level->bz = 0; if (player_actor != NULL) { pos_p = &player_actor->world.position; } else { pos_p = &actorx->world.position; } /* Try to move shop level actor to where the player currently is */ actorx->world.position = *pos_p; shop_block_flag = mFI_BlockKind2BkNum(&shop_level->bx, &shop_level->bz, mRF_BLOCKKIND_SHOP); if (Save_Get(scene_no) == SCENE_FG) { mSP_SetShopRareFurnitureChirashi(Common_Get(player_no), Save_Get(shop).items, mSP_GOODS_COUNT, NULL); Save_Get(shop).shop_info.not_loaded_before = FALSE; } if (shop_block_flag) { aSL_RenewShop(actorx, game); } } static void Shop_Level_Actor_dt(ACTOR* actorx, GAME* game) { // nothing } static void Shop_Level_Actor_draw(ACTOR* actorx, GAME* game) { // nothing } static void aSL_JudgeRenewShop(ACTOR* actorx, GAME* game) { if (Save_Get(scene_no) == SCENE_FG && mEv_CheckEvent(mEv_SAVED_RENEWSHOP) == FALSE) { if (mSP_GetShopLevel() < mSP_GetRealShopLevel()) { lbRTC_time_c now_time = Common_Get(time.rtc_time); lbRTC_time_c renewal_two_days = now_time; lbRTC_time_c renewal_one_day; u16 bargain_date; renewal_two_days.hour = mSP_GetShopOpenTime(); renewal_two_days.min = 0; renewal_two_days.sec = 0; lbRTC_Add_DD(&renewal_two_days, 2); renewal_one_day = now_time; lbRTC_Add_DD(&renewal_one_day, 1); bargain_date = mEv_get_bargain_day(); if (bargain_date != 0) { lbRTC_month_t bargain_month = (bargain_date >> 8) & 0xFF; lbRTC_day_t bargain_day = bargain_date & 0xFF; /* No upgrading shop if a Nook sale event happens within 2 days */ if ((now_time.month == bargain_month && now_time.day == bargain_day) || (renewal_two_days.month == bargain_month && renewal_two_days.day == bargain_day) || (renewal_one_day.month == bargain_month && renewal_one_day.day == bargain_day)) { return; } } { lbRTC_year_t now_year = now_time.year; lbRTC_month_t now_month = now_time.month; lbRTC_day_t max_day = lbRTC_GetDaysByMonth(now_year, now_time.month); lbRTC_day_t now_day = now_time.day; /* No upgrading shop if lottery day is within 2 days */ if (now_day == max_day || (renewal_two_days.day == lbRTC_GetDaysByMonth(renewal_two_days.year, renewal_two_days.month)) || (renewal_one_day.day == lbRTC_GetDaysByMonth(renewal_one_day.year, renewal_one_day.month))) { return; } /* Don't upgrade shop on sale day */ if ((now_month == lbRTC_NOVEMBER && now_day == (lbRTC_Weekly_day(now_year, lbRTC_NOVEMBER, 4, lbRTC_THURSDAY) + 1)) || (renewal_two_days.month == lbRTC_NOVEMBER && renewal_two_days.day == (lbRTC_Weekly_day(renewal_two_days.year, lbRTC_NOVEMBER, 4, lbRTC_THURSDAY) + 1)) || (renewal_one_day.month == lbRTC_NOVEMBER && renewal_one_day.day == (lbRTC_Weekly_day(renewal_one_day.year, lbRTC_NOVEMBER, 4, lbRTC_THURSDAY) + 1))) { return; } } mEv_EventON(mEv_SAVED_RENEWSHOP); Save_Get(shop).renewal_time = renewal_two_days; Save_Get(shop).shop_info.send_upgrade_notice = TRUE; Save_Get(shop).shop_info.upgrading_today = TRUE; } } if (Save_Get(scene_no) == SCENE_FG && mEv_CheckEvent(mEv_SAVED_RENEWSHOP) == TRUE) { lbRTC_time_c now_time = Common_Get(time.rtc_time); lbRTC_time_c renewal_time = Save_Get(shop).renewal_time; lbRTC_Sub_DD(&renewal_time, 2); if (lbRTC_IsOverTime(&now_time, &renewal_time) == lbRTC_OVER) { mEv_EventOFF(mEv_SAVED_RENEWSHOP); Save_Get(shop).shop_info.upgrading_today = FALSE; Save_Get(shop).shop_info.send_upgrade_notice = FALSE; return; } } aSL_SetRenewalChiraswhi_Notice(); mSP_SetRenewalChiraswhi_AppoDay(); } static void aSL_ExchangeShopGoodsInGame(ACTOR* actorx, GAME* game, lbRTC_hour_t hour) { lbRTC_time_c now_time = Common_Get(time.rtc_time); lbRTC_hour_t now_hour = now_time.hour; if (mEv_CheckEvent(mEv_SAVED_RENEWSHOP) == FALSE && Save_Get(scene_no) == SCENE_FG && now_hour >= hour && mSP_CheckExchangeDay2()) { if (mSP_CheckExchangeMonth()) { mSP_LotteryLineUp_ZeldaMalloc(); } mSP_NewExchangeDay(); mSP_ExchangeLineUp_ZeldaMalloc(); } } static void aSL_ReportShopOpen2Event(void) { int status = mSP_ShopOpen(); // @unused if (mSP_ShopOpen() == mSP_SHOP_STATUS_OPEN || mSP_ShopOpen() == mSP_SHOP_STATUS_OPENEVENT) { mEv_EventON(mEv_DAILY_OPEN_SHOP); } else { mEv_EventOFF(mEv_DAILY_OPEN_SHOP); } } static void Shop_Level_Actor_move(ACTOR* actorx, GAME* game) { GAME_PLAY* play = (GAME_PLAY*)game; ACTOR* player_actor = GET_PLAYER_ACTOR_ACTOR(play); xyz_t* pos_p; if (player_actor != NULL) { pos_p = &player_actor->world.position; } else { pos_p = &actorx->world.position; } actorx->world.position = *pos_p; aSL_JudgeRenewShop(actorx, game); aSL_ExchangeShopGoodsInGame(actorx, game, 6); aSL_ReportShopOpen2Event(); }