#include "m_post_office.h" #include "m_mail.h" #include "m_npc.h" #include "m_handbill.h" #include "m_museum.h" #include "m_name_table.h" #include "m_item_name.h" #include "m_private.h" #include "m_string.h" #include "m_house.h" #include "m_event.h" #include "m_field_info.h" #include "m_play.h" #include "libultra/libultra.h" #include "m_common_data.h" #include "m_scene_table.h" static int mPO_keep_contents(Mail_c* mail) { int res = FALSE; int free_idx = mMl_chk_mail_free_space(Save_Get(post_office).mail, mPO_MAIL_STORAGE_SIZE); if (free_idx >= 0) { mMl_copy_mail(Save_Get(post_office).mail + free_idx, mail); mMl_clear_mail(mail); res = TRUE; } return res; } extern int mPO_count_mail(int house_no) { int used = mMl_count_use_mail_space(Save_Get(homes[house_no]).mailbox, HOME_MAILBOX_SIZE); Mail_c* mail = Save_Get(post_office).mail; int i; for (i = 0; i < mPO_MAIL_STORAGE_SIZE; i++) { if (house_no == mMl_hunt_for_send_address(mail)) { used++; } mail++; } return used; } extern int mPO_get_keep_mail_sum() { PostOffice_c* post_office = Save_GetPointer(post_office); return post_office->keep_mail_sum_players + post_office->keep_mail_sum_npcs; } static void mPO_adjust_keep_mail() { Mail_c* mail = Save_Get(post_office).mail; int i; s16 recipient_flags = 0; s16 keep_mail_player_num = 0; for (i = 0; i < mPO_MAIL_STORAGE_SIZE; i++) { if (mMl_check_not_used_mail(mail) == FALSE) { int house_idx = mMl_hunt_for_send_address(mail); if (house_idx != -1) { keep_mail_player_num++; recipient_flags |= (1 << house_idx); } else { mMl_clear_mail(mail); } } mail++; } Save_Set(post_office.mail_recipient_flags, recipient_flags); Save_Set(post_office.keep_mail_sum_players, keep_mail_player_num); Save_Set(post_office.keep_mail_sum_npcs, 0); } static int mPO_receipt_check_mail(Mail_c* mail) { int res = FALSE; switch (mail->header.recipient.type) { case mMl_NAME_TYPE_PLAYER: { int house_idx = mMl_hunt_for_send_address(mail); if (house_idx != -1 && mPO_count_mail(house_idx) < HOME_MAILBOX_SIZE) { res = mPO_keep_contents(mail); if (res == TRUE) { Save_Get(post_office.mail_recipient_flags) |= (1 << house_idx); Save_Get(post_office.keep_mail_sum_players)++; } } break; } case mMl_NAME_TYPE_NPC: { if (mNpc_ReceiveHPMail(mail) == FALSE) { mNpc_SendMailtoNpc(mail); } res = mPO_keep_contents(mail); if (res == TRUE) { Save_Get(post_office).keep_mail_sum_npcs++; } break; } case mMl_NAME_TYPE_MUSEUM: { mMsm_SendMuseumMail(mail); mMl_clear_mail(mail); Save_Get(post_office).keep_mail_sum_npcs++; res = TRUE; break; } } return res; } extern int mPO_receipt_proc(Mail_c* mail, int send_type) { int res = FALSE; switch (send_type) { case mPO_SENDTYPE_MAIL: { res = mPO_receipt_check_mail(mail); break; } case mPO_SENDTYPE_LEAFLET: { mMl_copy_mail(&Save_Get(post_office).leaflet, mail); Save_Set(post_office.leaflet_recipient_flags.leaflet_flags, 0); res = TRUE; break; } case mPO_SENDTYPE_EVENT_LEAFLET: { mMl_copy_mail(&Save_Get(post_office).event_leaflet, mail); Save_Set(post_office.leaflet_recipient_flags.event_flags, 0); res = TRUE; break; } } return res; } static int mPO_copy_contents(int house_no, Mail_c* mail) { int res = FALSE; int free_slot = mMl_chk_mail_free_space(Save_Get(homes[house_no]).mailbox, HOME_MAILBOX_SIZE); if (free_slot >= 0) { mMl_copy_mail(Save_Get(homes[house_no]).mailbox + free_slot, mail); res = TRUE; } return res; } static void mPO_delivery_mail_with_item(Mail_c* mail, int mail_no, mActor_name_t present, PersonalID_c* pid) { int header_back_start; mHandbill_Load_HandbillFromRom(mail->content.header, &header_back_start, mail->content.footer, mail->content.body, mail_no); mail->content.font = mMl_FONT_0; mail->content.header_back_start = header_back_start; mail->content.mail_type = 7; mail->content.paper_type = ITM_PAPER55; mail->present = present; mMl_set_to_plname(mail, pid); } static int mPO_delivery_mail_with_order_ftr_sub(int house_no, PersonalID_c* pid, mPr_catalog_order_c* order) { Mail_c mail; u8 item_name[mIN_ITEM_NAME_LEN]; mMl_clear_mail(&mail); mIN_copy_name_str(item_name, order->item); mHandbill_Set_free_str(0, item_name, mIN_ITEM_NAME_LEN); mPO_delivery_mail_with_item(&mail, 0x049 + order->shop_level, order->item, pid); return mPO_copy_contents(house_no, &mail); } static void mPO_delivery_mail_with_order_ftr(int house_no, int player_no) { Private_c* priv = Save_GetPointer(private[player_no]); if (priv->exists == TRUE) { mPr_catalog_order_c* order = priv->catalog_orders; int i; for (i = 0; i < mPr_CATALOG_ORDER_NUM; i++) { if (order->item != EMPTY_NO) { if (mPO_delivery_mail_with_order_ftr_sub(house_no, &priv->player_ID, order) == FALSE) { return; } order->item = EMPTY_NO; } order++; } } } static void mPO_delivery_mail_with_ticket_set_free_str(lbRTC_month_t month) { u8 month_str[9]; u8 day_str[4]; int days = lbRTC_GetDaysByMonth(Common_Get(time.rtc_time.year), month); mString_Load_MonthStringFromRom(month_str, month); mString_Load_DayStringFromRom(day_str, days); mHandbill_Set_free_str(4, month_str, 9); mHandbill_Set_free_str(5, day_str, 4); } static int mPO_delivery_mail_with_ticket_sub(int house_no, PersonalID_c* pid, mActor_name_t present) { Mail_c mail; mMl_clear_mail(&mail); mPO_delivery_mail_with_item(&mail, 0x057, present, pid); return mPO_copy_contents(house_no, &mail); } static void mPO_delivery_mail_with_ticket(int house_no, int player_no) { mActor_name_t ticket; Private_c* priv = Save_GetPointer(private[player_no]); if (priv->exists == TRUE) { int ticket_num = priv->inventory.lotto_ticket_mail_storage; if (ticket_num != 0) { int minus_ticket; mActor_name_t ticket_id; lbRTC_month_t ticket_month = priv->inventory.lotto_ticket_expiry_month; mPO_delivery_mail_with_ticket_set_free_str(ticket_month); ticket = ITM_TICKET_START + (ticket_month - 1) * 8; for (ticket_num; ticket_num != 0; ticket_num -= minus_ticket) { minus_ticket = ticket_num < 5 ? ticket_num : 5; ticket_id = ticket + minus_ticket - 1; if (mPO_delivery_mail_with_ticket_sub(house_no, &priv->player_ID, ticket_id) == FALSE) { break; } } } priv->inventory.lotto_ticket_mail_storage = ticket_num; } } static int mPO_delivery_mail_sub(int house_no) { PostOffice_c* post_office; Mail_c* po_mail; int i; int res = TRUE; po_mail = Save_Get(post_office).mail; post_office = Save_GetPointer(post_office); for (i = 0; i < mPO_MAIL_STORAGE_SIZE; i++, po_mail++) { if (mMl_check_not_used_mail(po_mail) == FALSE) { int dst_house_no = mMl_hunt_for_send_address(po_mail); if (dst_house_no != -1) { if (house_no == mPO_DELIVER_ALL_HOUSES || dst_house_no == house_no) { if (mPO_copy_contents(dst_house_no, po_mail) == TRUE) { post_office->keep_mail_sum_players--; mMl_clear_mail(po_mail); } else { res = FALSE; // failed to deliver the mail, house mailbox is likely full } } } else { switch (po_mail->header.recipient.type) { case mMl_NAME_TYPE_PLAYER: post_office->keep_mail_sum_players--; break; } mMl_clear_mail(po_mail); } } } Save_Set(post_office.keep_mail_sum_npcs, 0); return res; } static void mPO_delivery_one_address_mail(int house_no) { if (mPO_delivery_mail_sub(house_no) == TRUE) { s16 mask = (1 << house_no) ^ 0b1111; Save_Get(post_office.mail_recipient_flags) &= mask; // clear out delivered houses } } static void mPO_delivery_one_address_special_mail(int house_no) { int player_no = mHS_get_pl_no(house_no); mPO_delivery_mail_with_ticket(house_no, player_no); mPO_delivery_mail_with_order_ftr(house_no, player_no); } static void mPO_delivery_one_address_leaflet(s16* leaflet_received_flags, Mail_c* leaflet, int house_no) { if ((((*leaflet_received_flags) >> house_no) & 1) == FALSE) { mHm_hs_c* house = Save_GetPointer(homes[house_no]); if (house->ownerID.land_id == 0xFFFF) { *leaflet_received_flags |= (1 << house_no); // unclaimed houses are marked "received" } else { int player_no = mHS_get_pl_no(house_no); if (player_no < mPr_FOREIGNER && mEv_ArbeitPlayer(player_no) == FALSE) { mMl_set_to_plname(leaflet, &house->ownerID); if (mPO_copy_contents(house_no, leaflet) == TRUE) { *leaflet_received_flags |= (1 << house_no); } } } } } static void mPO_delivery_one_address_event_leaflet(int house_no) { Mail_c* ev_leaflet = &Save_Get(post_office).event_leaflet; int special_type = mEv_get_special_event_type(); int leaflet_event_type; switch (ev_leaflet->content.mail_type) { case mMl_TYPE_SHOP_SALE_LEAFLET: leaflet_event_type = mEv_EVENT_SHOP_SALE; break; case mMl_TYPE_BROKER_SALE_LEAFLET: leaflet_event_type = mEv_EVENT_BROKER_SALE; break; default: leaflet_event_type = -1; break; } if (leaflet_event_type == special_type) { mPO_delivery_one_address_leaflet(&Save_Get(post_office).leaflet_recipient_flags.event_flags, ev_leaflet, house_no); } } extern int mPO_delivery_one_address(int house_no) { mPO_delivery_one_address_mail(house_no); mPO_delivery_one_address_leaflet(&Save_Get(post_office).leaflet_recipient_flags.leaflet_flags, &Save_Get(post_office).leaflet, house_no); mPO_delivery_one_address_event_leaflet(house_no); } static void mPO_delivery_mail() { mPO_delivery_mail_sub(mPO_DELIVER_ALL_HOUSES); mPO_adjust_keep_mail(); } static void mPO_delivery_leaflet() { int house_no; for (house_no = 0; house_no < mHS_HOUSE_NUM; house_no++) { mPO_delivery_one_address_leaflet(&Save_Get(post_office).leaflet_recipient_flags.leaflet_flags, &Save_Get(post_office).leaflet, house_no); mPO_delivery_one_address_event_leaflet(house_no); } } extern void mPO_delivery_all_address_proc() { mPO_delivery_mail(); mPO_delivery_leaflet(); } static int mPO_make_post_man(GAME_PLAY* play) { static int bx_add[2] = { -1, 1 }; static int ux_table[2] = { UT_X_NUM - 1, 0 }; int pl_block_x; int pl_block_z; u32 block_kind; int po_block_x; int po_block_z; int res = FALSE; if (Save_Get(scene_no) == SCENE_FG) { mFI_BlockKind2BkNum(&pl_block_x, &pl_block_z, mRF_BLOCKKIND_PLAYER); block_kind = mFI_BkNum2BlockKind(play->block_table.block_x, play->block_table.block_z); if (block_kind != mRF_BLOCKKIND_NONE) { if ((block_kind & mRF_BLOCKKIND_PLAYER) != 0) { int bx_add_idx; int spawned_postman; mFI_BlockKind2BkNum(&po_block_x, &po_block_z, mRF_BLOCKKIND_POSTOFFICE); bx_add_idx = pl_block_x >= po_block_x ? 0 : 1; spawned_postman = (*Common_Get(clip).npc_clip->setupActor_proc)(play, SP_NPC_POST_MAN, -1, -1, 0, play->block_table.block_x + bx_add[bx_add_idx], play->block_table.block_z, ux_table[bx_add_idx], 7); if (spawned_postman == TRUE) { res = TRUE; } } else if ((block_kind & mRF_BLOCKKIND_POSTOFFICE) != 0) { if (Common_Get(force_mail_delivery_flag) == TRUE) { int post_utx; int post_utz; int spawned_postman; ACTOR* post_office_structure = Actor_info_fgName_search(&play->actor_info, POST_OFFICE, ACTOR_PART_ITEM); if (post_office_structure != NULL) { mFI_Wpos2UtNum_inBlock(&post_utx, &post_utz, post_office_structure->world.position); spawned_postman = (*Common_Get(clip).npc_clip->setupActor_proc)(play, SP_NPC_POST_MAN, -1, -1, 1, play->block_table.block_x, play->block_table.block_z, post_utx - 3, post_utz); if (spawned_postman == TRUE) { res = TRUE; } } } } else { mPO_delivery_all_address_proc(); res = TRUE; } } else { mPO_delivery_all_address_proc(); res = TRUE; } } else { mPO_delivery_all_address_proc(); res = TRUE; } return res; } static void mPO_set_next_delivery_time(lbRTC_time_c* time) { if (time->hour < 9) { time->hour = 9; } else if (time->hour < 17) { time->hour = 17; } else { lbRTC_Add_DD(time, 1); time->hour = 9; } time->min = 0; time->sec = 0; lbRTC_TimeCopy(&Save_Get(post_office).delivery_time, time); } static void mPO_delivery_proc(GAME_PLAY* play) { lbRTC_time_c time; lbRTC_TimeCopy(&time, Common_GetPointer(time.rtc_time)); if ((lbRTC_IsOverTime(&Save_Get(post_office).delivery_time, &time) == lbRTC_OVER || Common_Get(force_mail_delivery_flag) == TRUE) && (mPO_make_post_man(play) == TRUE) ) { mPO_set_next_delivery_time(&time); Common_Set(force_mail_delivery_flag, FALSE); } } static void mPO_first_delivery_proc() { int deliver = FALSE; lbRTC_time_c time; lbRTC_TimeCopy(&time, Common_GetPointer(time.rtc_time)); if (lbRTC_IsOverTime(&Save_Get(post_office).delivery_time, &time) == lbRTC_OVER || Common_Get(force_mail_delivery_flag) == TRUE) { deliver = TRUE; mPO_set_next_delivery_time(&time); Common_Set(force_mail_delivery_flag, FALSE); } if (deliver == TRUE) { mPO_delivery_mail(); } if (mLd_PlayerManKindCheck() == FALSE) { int house_no = mHS_get_arrange_idx(Common_Get(player_no)); mPO_delivery_one_address_special_mail(house_no); } if (deliver == TRUE) { mPO_delivery_leaflet(); } } extern void mPO_business_proc(GAME_PLAY* play) { if ((Common_Get(clip).demo_clip == NULL && Common_Get(clip).demo_clip2 == NULL) || (Common_Get(clip).demo_clip != NULL && Common_Get(clip).demo_clip->type == mDemo_CLIP_TYPE_INTRO_DEMO) ) { int scene = Save_Get(scene_no); switch (scene) { default: mPO_delivery_proc(play); break; case SCENE_PLAYERSELECT: case SCENE_PLAYERSELECT_2: case SCENE_PLAYERSELECT_3: case SCENE_PLAYERSELECT_SAVE: case SCENE_TITLE_DEMO: return; } } } extern void mPO_first_work() { lbRTC_time_c* time = &Save_Get(save_check).time; if (mTM_AreTimesEqual(time, &mTM_rtcTime_clear_code) == FALSE && lbRTC_IsOverRTC(time) == FALSE) { Common_Set(force_mail_delivery_flag, TRUE); } mPO_first_delivery_proc(); mPO_adjust_keep_mail(); } extern void mPO_post_office_init() { bzero(Save_GetPointer(post_office), sizeof(PostOffice_c)); mMl_clear_mail_box(Save_Get(post_office).mail, mPO_MAIL_STORAGE_SIZE); mMl_clear_mail(&Save_Get(post_office).leaflet); mMl_clear_mail(&Save_Get(post_office).event_leaflet); Save_Get(post_office).leaflet_recipient_flags.raw = 0x000F000F; lbRTC_TimeCopy(&Save_Get(post_office).delivery_time, Common_GetPointer(time.rtc_time)); }