From f7fb676f550c2936ddd049d232b4c427a0f7a9ce Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Wed, 26 Jul 2023 12:00:08 -0400 Subject: [PATCH] Implement & link m_museum.c --- config/rel_slices.yml | 5 + include/m_collision_bg.h | 1 + include/m_field_info.h | 1 + include/m_mail.h | 11 + include/m_museum.h | 49 ++- include/m_museum_display.h | 21 ++ include/m_name_table.h | 8 + include/m_private.h | 4 +- include/m_shop.h | 1 + rel/m_museum.c | 677 +++++++++++++++++++++++++++++++++++++ rel/m_private.c | 8 +- 11 files changed, 770 insertions(+), 16 deletions(-) create mode 100644 rel/m_museum.c diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 19e96035..93f02d75 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -85,6 +85,11 @@ m_mail_password_check.c: m_lib.c: .text: [0x803BAB0C, 0x803BB960] .rodata: [0x80642640, 0x80642680] +m_museum.c: + .text: [0x803C6228, 0x803C74C0] + .rodata: [0x80642938, 0x80642950] + .data: [0x8065A280, 0x8065A308] + .bss: [0x81298A00, 0x81298B40] m_mushroom.c: .text: [0x803C8090, 0x803C90A8] .rodata: [0x80642950, 0x80642960] diff --git a/include/m_collision_bg.h b/include/m_collision_bg.h index a947f327..919baf45 100644 --- a/include/m_collision_bg.h +++ b/include/m_collision_bg.h @@ -104,6 +104,7 @@ extern void mCoBG_BgCheckControll(xyz_t* reverse_pos, ACTOR* actor, f32 check_ra extern int mCoBG_Height2GetLayer(f32 height); extern void mCoBG_SetPlussOffset(xyz_t wpos, s16 offset, s16 new_attrib); extern int mCoBG_GetLayer(const xyz_t* wpos); +extern int mCoBG_BnumUnum2HoleNumber(int block_x, int block_z, int ut_x, int ut_z); extern f32 mCoBG_GetWaterHeight_File(xyz_t wpos, char* file, int line); #define mCoBG_GetWaterHeight(wpos) mCoBG_GetWaterHeight_File(wpos, __FILE__, __LINE__) diff --git a/include/m_field_info.h b/include/m_field_info.h index 6a9891ab..5db7729f 100644 --- a/include/m_field_info.h +++ b/include/m_field_info.h @@ -153,6 +153,7 @@ extern void mFI_FieldMove(xyz_t player_wpos); extern int mFI_search_unit_around(xyz_t* wpos, mActor_name_t item); extern void mFI_BlockDepositOFF(u16* deposit, int ut_x, int ut_z); extern void mFI_PullTanukiPathTrees(); +extern int mFI_CheckBlockKind_OR(int block_x, int block_z, u32 kind); extern void mFI_PrintNowBGNum(gfxprint_t* gfxprint); extern void mFI_PrintFgAttr(gfxprint_t* gfxprint); diff --git a/include/m_mail.h b/include/m_mail.h index 71dabf14..4e5d9de1 100644 --- a/include/m_mail.h +++ b/include/m_mail.h @@ -19,6 +19,8 @@ extern "C" { #define mMl_POSTOFFICE_GIFT_NUM 4 +#define mMl_MUSEUM_INFO_MAIL_NO 189 // TODO: enum? + enum { mMl_NAME_TYPE_PLAYER, mMl_NAME_TYPE_NPC, @@ -38,6 +40,15 @@ enum { }; enum { + mMl_DATA, + mMl_DATA2, + + mMl_DATA_NUM +}; + +enum { + mMl_TYPE_MUSEUM = 0, + mMl_TYPE_1 = 1, mMl_TYPE_SHOP_SALE_LEAFLET = 2, mMl_TYPE_BROKER_SALE_LEAFLET = 3 }; diff --git a/include/m_museum.h b/include/m_museum.h index f6ca12fe..6c00c65a 100644 --- a/include/m_museum.h +++ b/include/m_museum.h @@ -3,36 +3,63 @@ #include "types.h" #include "m_actor_type.h" +#include "m_mail.h" +#include "m_museum_display.h" +#include "m_collision_bg.h" #ifdef __cplusplus extern "C" { #endif #define mMsm_REMAIL_SLOTS 30 +#define mMsm_MAX_MAIL 3 +#define mMsm_DEPOSIT_FOSSIL_MAX 5 -/* sizeof(mMsm_remail_display_c) = 1 */ -typedef struct museum_remail_display_s { - u8 display_type_upper:4; - u8 display_type_lower:4; -} mMsm_remail_display_c; +enum { + mMsm_FOSSIL_TYPE_SINGLE, + mMsm_FOSSIL_TYPE_MULTI, + + mMsm_FOSSIL_TYPE_NUM +}; + +enum { + mMsm_REMAIL_KIND_CLEAR, + mMsm_REMAIL_KIND_CANNOT_DONATE, + mMsm_REMAIL_KIND_DONATED, + mMsm_REMAIL_KIND_ALREADY_DONATED, + mMsm_REMAIL_KIND_FOREIGNER, + + mMsm_REMAIL_KIND_NUM, +}; /* sizeof(mMsm_remail_info_c) == 0x4C */ typedef struct museum_remail_info_s { - /* 0x00 */ mMsm_remail_display_c types[mMsm_REMAIL_SLOTS / 2]; /* display types for items */ + /* 0x00 */ u8 types[mMsm_REMAIL_SLOTS / 2]; /* display types for items */ /* 0x10 */ mActor_name_t items[mMsm_REMAIL_SLOTS]; /* item storage */ } mMsm_remail_info_c; -/* sizeof(mMsm_mail_info_c) == 0x4E */ -typedef struct museum_mail_info_s { +/* sizeof(mMsm_record_c) == 0x4E */ +typedef struct museum_record_s { u8 contacted:1; /* set to TRUE when the museum has contacted the player */ - u8 unused:1; /* unused where this is used, if at all */ + u8 remail_pending:1; /* set to TRUE when the museum has non-fossil letters pending */ u8 send_info_mail:1; /* if set to true, museum info mail will be sent */ - u8 stored_item_num:5; /* number of stored items */ + u8 stored_fossil_num:5; /* number of stored fossils */ mMsm_remail_info_c remail_info; /* remail info */ -} mMsm_mail_info_c; +} mMsm_record_c; +extern void mMsm_ClearRecord(mMsm_record_c* record); +extern void mMsm_GetMuseumMailName(Mail_nm_c* name); +extern void mMsm_SendInformationMail(); extern void mMsm_SendMuseumMail(Mail_c* mail); +extern int mMsm_GetDepositAbleNum(mActor_name_t* fg_items, mCoBG_Collision_u* col_data); +extern void mMsm_DepositItemBlock_cancel(mActor_name_t* fg_items, mActor_name_t deposit_item, mCoBG_Collision_u* col_data, u16* deposit, u16* cancel_ut, u8 valid_ut_count); +extern void mMsm_DepositItemBlock(mActor_name_t* fg_items, mActor_name_t item, int block_x, int block_z, u16* deposit, u8 valid_ut_count); +extern int mMsm_RecordDepositFossil(u8* record, mActor_name_t item, int block_x); +extern u8 mMsm_GetDepositBlockNum(u8 record); +extern void mMsm_DepositFossil(u8 deposit_record, int fossil_count, u16* cancel_ut, int send_order_info); +extern void mMsm_SetCompMail(); +extern void mMsm_SendCompMail(); #ifdef __cplusplus } diff --git a/include/m_museum_display.h b/include/m_museum_display.h index 2c070ef8..394a8b97 100644 --- a/include/m_museum_display.h +++ b/include/m_museum_display.h @@ -2,6 +2,7 @@ #define M_MUSEUM_DISPLAY_H #include "types.h" +#include "m_actor_type.h" #ifdef __cplusplus extern "C" { @@ -14,6 +15,19 @@ extern "C" { #define mMmd_FISH_BIT_NUM 21 #define mMmd_INSECT_BIT_NUM 21 +#define mMmd_FOSSIL_NUM 25 +#define mMmd_ART_NUM 15 +#define mMmd_INSECT_NUM 40 +#define mMmd_FISH_NUM 40 + +enum { + mMmd_DISPLAY_CANNOT_DONATE, /* Item cannot be donated */ + mMmd_DISPLAY_CAN_DONATE, /* Item can be donated */ + mMmd_DISPLAY_ALREADY_DONATED, /* Item has already been donated */ + + mMmd_DISPLAY_NUM +}; + /* 4 bits per donatable item */ #define mMmd_BIT_INFO(info, category, index) \ (((info).category[(index) / 2] >> (((index) & 1) << 2)) & 0x0F) @@ -31,6 +45,13 @@ typedef struct museum_display_info_s { /* 0x2A */ u8 insect_bit[mMmd_INSECT_BIT_NUM]; } mMmd_info_c; +extern int mMmd_GetDisplayInfo(mActor_name_t item); +extern int mMmd_RequestMuseumDisplay(mActor_name_t item); +extern int mMmd_CountDisplayedFossil(); +extern int mMmd_CountDisplayedArt(); +extern int mMmd_CountDisplayedInsect(); +extern int mMmd_CountDisplayedFish(); + #ifdef __cplusplus } #endif diff --git a/include/m_name_table.h b/include/m_name_table.h index 635b0a24..3fef1daa 100644 --- a/include/m_name_table.h +++ b/include/m_name_table.h @@ -142,6 +142,8 @@ extern int mNT_check_unknown(mActor_name_t item_no); #define GRASS_B (GRASS_A + 1) #define GRASS_C (GRASS_B + 1) +#define BURIED_PITFALL0 0x002A + #define TREE_BEES 0x005E #define TREE_FTR (TREE_BEES + 1) #define TREE_LIGHTS (TREE_FTR + 1) @@ -375,6 +377,10 @@ extern int mNT_check_unknown(mActor_name_t item_no); #define FTR_TAPEDECK 0x1E58 +#define FTR_DINO_TRICERA_SKULL 0x1EEC + +#define FTR_DINO_TRILOBITE_WEST 0x1F4F + #define FTR_PIGGY_BANK 0x1FAC #define FTR_TISSUE 0x1FB0 @@ -882,6 +888,8 @@ extern int mNT_check_unknown(mActor_name_t item_no); #define FTR_POST_MODEL 0x3020 +#define FTR_MUSEUM_MODEL 0x3030 + #define FTR_ORANGEBOX 0x30F8 #define FTR_COLLEGERULE 0x30FC diff --git a/include/m_private.h b/include/m_private.h index e1dc80c7..66ab03e9 100644 --- a/include/m_private.h +++ b/include/m_private.h @@ -25,6 +25,8 @@ extern "C" { #define mPr_FLAG_POSTOFFICE_GIFT1 (1 << 3) // 10,000,000 Bells #define mPr_FLAG_POSTOFFICE_GIFT2 (1 << 4) // 100,000,000 Bells #define mPr_FLAG_POSTOFFICE_GIFT3 (1 << 5) // 999,999,999 Bells +#define mPr_FLAG_MUSEUM_COMP_HANDBILL_SCHEDULED (1 << 6) // player is scheduled to receive completion letter & reward +#define mPr_FLAG_MUSEUM_COMP_HANDBILL_RECEIVED (1 << 7) // player has received the completion letter & reward #define mPr_MONEY_POWER_MIN -80 @@ -178,7 +180,7 @@ struct private_s { /* 0x0014 */ s8 gender; /* gender/sex of player */ /* 0x0015 */ s8 face; /* face type of player */ /* 0x0016 */ u8 reset_count; /* times player has reset */ - /* 0x0017 */ mMsm_mail_info_c museum_mail_info; /* museum items & remail info */ + /* 0x0017 */ mMsm_record_c museum_record; /* museum items & remail info */ /* must be a struct due to alignment of first member */ /* 0x0068 */ struct { diff --git a/include/m_shop.h b/include/m_shop.h index 495f6b01..8aa1ae43 100644 --- a/include/m_shop.h +++ b/include/m_shop.h @@ -129,6 +129,7 @@ extern void mSP_RandomUmbSelect(mActor_name_t* item_buf, int item_buf_count); extern int mSP_GetShopLevel(); extern u32 mSP_ItemNo2ItemPrice(mActor_name_t item_no); extern int mSP_SearchItemCategoryPriority(mActor_name_t item_no, int category, int priority, GAME* unused); // not sure if it's actually a GAME* +extern mActor_name_t mSP_RandomOneFossilSelect(int multi_fossil); extern void mItemDebug_ItemDebugMain(); extern void mItemDebug_ItemDebugDraw(gfxprint_t* gfxprint); diff --git a/rel/m_museum.c b/rel/m_museum.c new file mode 100644 index 00000000..6a25b193 --- /dev/null +++ b/rel/m_museum.c @@ -0,0 +1,677 @@ +#include "m_museum.h" + +#include "libultra/libultra.h" +#include "m_font.h" +#include "m_mail.h" +#include "m_handbill.h" +#include "m_private.h" +#include "m_shop.h" +#include "m_name_table.h" +#include "m_msg.h" +#include "m_field_info.h" +#include "m_random_field_h.h" +#include "m_common_data.h" + +static u8 l_museum_name_str[PLAYER_NAME_LEN] = { CHAR_M, CHAR_u, CHAR_s, CHAR_e, CHAR_u, CHAR_m, CHAR_SPACE, CHAR_SPACE }; /* "Museum " */ + +static u8 present_name[mIN_ITEM_NAME_LEN]; /* TODO: reversed bss order */ +static Mail_c l_mmsm_mail; + +extern void mMsm_ClearRecord(mMsm_record_c* record) { + bzero(record, sizeof(mMsm_record_c)); +} + +extern void mMsm_GetMuseumMailName(Mail_nm_c* name) { + mPr_ClearPersonalID(&name->personalID); + mPr_CopyPlayerName(name->personalID.player_name, l_museum_name_str); + name->type = mMl_NAME_TYPE_MUSEUM; +} + +static void mMsm_OrderInformationMail() { + Private_c* priv = Save_Get(private); + int i; + + for (i = 0; i < PLAYER_NUM; i++) { + if (mPr_NullCheckPersonalID(&priv->player_ID) == FALSE && mPr_CheckMuseumAddress(priv) == FALSE) { + priv->museum_record.send_info_mail = TRUE; + } + + priv++; + } +} + +extern void mMsm_SendInformationMail() { + Private_c* priv = Save_Get(private); + int i; + + for (i = 0; i < PLAYER_NUM; i++) { + if (mPr_NullCheckPersonalID(&priv->player_ID) == FALSE && mPr_CheckMuseumInfoMail(priv)) { + if (mMl_send_mail_box(&priv->player_ID, i, &l_mmsm_mail, EMPTY_NO, ITM_PAPER24, mMl_MUSEUM_INFO_MAIL_NO, l_museum_name_str, mMl_DATA2) == TRUE) { + priv->museum_record.contacted = TRUE; + priv->museum_record.send_info_mail = FALSE; + } + } + + priv++; + } +} + +static void mMsm_GetFossil(mActor_name_t* fossil) { + static int hit_table[mMsm_FOSSIL_TYPE_NUM] = { FALSE, TRUE }; + + *fossil = mSP_RandomOneFossilSelect(hit_table[RANDOM(mMsm_FOSSIL_TYPE_NUM)]); +} + +static int mMsm_GetFossilMailNo(mActor_name_t fossil) { + static int mail_no_table[25] = { + 0x10E, 0x110, 0x10F, 0x111, + 0x113, 0x112, 0x114, 0x116, + 0x115, 0x117, 0x119, 0x118, + 0x11A, 0x11B, 0x11C, 0x11D, + 0x11E, 0x11F, 0x120, 0x121, + 0x126, 0x125, 0x123, 0x124, + 0x122 + }; + + int type = 0; // invalid item + + if (fossil >= FTR_DINO_TRICERA_SKULL && fossil <= FTR_DINO_TRILOBITE_WEST) { + type = 1; // valid fossil + } + + return mail_no_table[type != 0 ? (fossil - FTR_DINO_TRICERA_SKULL) >> 2 : 0]; +} + +static void mMsm_GetRemailAddIdx(int* add, int* shift, int idx) { + *add = (idx << 2) / 8; + *shift = idx - (*add * 2); +} + +static int mMsm_Idx2RemailKind(mMsm_remail_info_c* remail_info, int idx) { + int kind = -1; + int add = 0; + int shift = 0; + + if (remail_info != NULL && idx >= 0 && idx < mMsm_REMAIL_SLOTS) { + mMsm_GetRemailAddIdx(&add, &shift, idx); + kind = (remail_info->types[add] >> (shift << 2)) & 7; + } + + return kind; +} + +static int mMsm_GetRemailFreeIdx(mMsm_remail_info_c* remail_info) { + int idx = -1; + + if (remail_info != NULL) { + int i; + + for (i = 0; i < mMsm_REMAIL_SLOTS; i++) { + int kind = mMsm_Idx2RemailKind(remail_info, i); + + if (kind == mMsm_REMAIL_KIND_CLEAR || kind >= mMsm_REMAIL_KIND_NUM) { + idx = i; + break; + } + } + } + + return idx; +} + +static void mMsm_Idx2SetRemailInfo(mMsm_remail_info_c* remail_info, int idx, int remail_type, mActor_name_t item_no) { + int slot_idx = 0; + int nibble = 0; + + if (remail_info != NULL && idx >= 0 && idx < mMsm_REMAIL_SLOTS) { + int i; + + mMsm_GetRemailAddIdx(&slot_idx, &nibble, idx); + i = slot_idx; + + if (nibble == 0) { + u8 raw = remail_info->types[i]; + remail_info->types[i] = (raw & 0xF0) | remail_type & 7; + } + else { + u8 raw = remail_info->types[i]; + remail_info->types[i] = (raw & 0x0F) | (remail_type & 7) << 4; + } + + remail_info->items[idx] = item_no; + } +} + +static void mMsm_Idx2ClearRemailInfo(mMsm_remail_info_c* remail_info, int idx) { + mMsm_Idx2SetRemailInfo(remail_info, idx, mMsm_REMAIL_KIND_CLEAR, EMPTY_NO); +} + +static void mMsm_PushRemailInfo(mMsm_remail_info_c* remail_info) { + int active = TRUE; + + if (remail_info != NULL) { + while (active == TRUE) { + int first_free_idx; + + active = FALSE; + first_free_idx = mMsm_GetRemailFreeIdx(remail_info); + + if (first_free_idx != -1) { + int used_slot_idx = first_free_idx + 1; + + /* Count up until we've found the first used slot or reach the end */ + while (used_slot_idx < mMsm_REMAIL_SLOTS) { + int remail_type = mMsm_Idx2RemailKind(remail_info, used_slot_idx); + + if (remail_type > mMsm_REMAIL_KIND_CLEAR && remail_type < mMsm_REMAIL_KIND_NUM) { + mMsm_Idx2SetRemailInfo(remail_info, first_free_idx, remail_type, remail_info->items[used_slot_idx]); + mMsm_Idx2ClearRemailInfo(remail_info, used_slot_idx); + active = TRUE; /* Continue searching */ + break; + } + + used_slot_idx++; + } + } + } + } +} + +static void mMsm_SetRemailInfo(mMsm_remail_info_c* remail_info, Private_c* priv, mActor_name_t item) { + int kind = mMsm_REMAIL_KIND_CLEAR; + + if (item != EMPTY_NO) { + int free_idx; + int private_idx = mPr_GetPrivateIdx(&priv->player_ID); + + if (private_idx == -1) { + kind = mMsm_REMAIL_KIND_FOREIGNER; + } + else { + switch (mMmd_GetDisplayInfo(item)) { + case mMmd_DISPLAY_CANNOT_DONATE: + { + kind = mMsm_REMAIL_KIND_CANNOT_DONATE; + break; + } + + case mMmd_DISPLAY_CAN_DONATE: + { + kind = mMsm_REMAIL_KIND_DONATED; + mMmd_RequestMuseumDisplay(item); + break; + } + + case mMmd_DISPLAY_ALREADY_DONATED: + { + kind = mMsm_REMAIL_KIND_ALREADY_DONATED; + break; + } + } + } + + free_idx = mMsm_GetRemailFreeIdx(remail_info); + if (free_idx != -1) { + mMsm_Idx2SetRemailInfo(remail_info, free_idx, kind, item); + } + } +} + +static void mMsm_SendResultMail() { + static int remail_no_table[mMsm_REMAIL_KIND_NUM - 1] = { 0x22D, 0x22B, 0x22C, 0x22E }; + //static u8 present_name[mIN_ITEM_NAME_LEN]; /* TODO: reversed bss order */ + + int send_num[PLAYER_NUM]; + Private_c* priv_p = Save_Get(private); + Private_c* priv = priv_p; + mActor_name_t present; + u8 send_flags = 0b1111; + mActor_name_t fossil = EMPTY_NO; + mMsm_remail_info_c* remail_info; + int idx; + int i; + + bzero(send_num, PLAYER_NUM * sizeof(int)); + + /* Send 'remail' info */ + for (i = 0; i < PLAYER_NUM; i++) { + if (mPr_NullCheckPersonalID(&priv->player_ID) == FALSE) { + mMsm_record_c* record = &priv->museum_record; + if (record->contacted == TRUE) { + int landname_len; + mActor_name_t item; + + remail_info = &record->remail_info; + for (idx = 0; idx < mMsm_REMAIL_SLOTS; idx++) { + int remail_kind; + + present = EMPTY_NO; + remail_kind = mMsm_Idx2RemailKind(remail_info, idx); + + if (remail_kind <= mMsm_REMAIL_KIND_CLEAR || remail_kind >= mMsm_REMAIL_KIND_NUM) { + break; /* Reached end of populated remail slots */ + } + + landname_len = mMsg_Get_Length_String(Save_Get(land_info.name), LAND_NAME_SIZE); + mHandbill_Set_free_str(mHandbill_FREE_STR0, Save_Get(land_info.name), landname_len); + + item = remail_info->items[idx]; + if (item != EMPTY_NO) { + mIN_copy_name_str(present_name, item); + mHandbill_Set_free_str(mHandbill_FREE_STR1, present_name, mIN_ITEM_NAME_LEN); + + if (remail_kind != mMsm_REMAIL_KIND_DONATED) { + present = remail_info->items[idx]; + } + } + + if (mMl_send_mail(&priv->player_ID, i, present, ITM_PAPER24, remail_no_table[remail_kind - 1], l_museum_name_str, mMl_DATA2)) { + mMsm_Idx2ClearRemailInfo(remail_info, idx); + send_num[i]++; + + if (send_num[i] >= mMsm_MAX_MAIL) { + send_flags &= ~(1 << i); + break; + } + } + else { + /* If attempted mail was unable to be received, remove this player from the send pool and stop processing */ + send_flags &= ~(1 << i); + break; + } + } + + mMsm_PushRemailInfo(remail_info); + } + else { + send_flags &= ~(1 << i); + } + } + else { + send_flags &= ~(1 << i); + } + + priv++; + } + + /* Send fossil mail */ + while (send_flags != 0) { + priv = priv_p; + for (i = 0; i < PLAYER_NUM; i++) { + if (((send_flags >> i) & 1) == 1) { + mMsm_record_c* record = &priv->museum_record; + if (record->stored_fossil_num != 0) { + int mail_no; + + mMsm_GetFossil(&fossil); + mail_no = mMsm_GetFossilMailNo(fossil); + + if (mMl_send_mail(&priv->player_ID, i, fossil, ITM_PAPER24, mail_no, l_museum_name_str, mMl_DATA2)) { + record->stored_fossil_num--; + send_num[i]++; + + if (send_num[i] >= mMsm_MAX_MAIL) { + send_flags &= ~(1 << i); + } + } + else { + send_flags &= ~(1 << i); + } + } + else { + send_flags &= ~(1 << i); + } + } + + priv++; + } + } +} + +extern void mMsm_SendMuseumMail(Mail_c* mail) { + Mail_nm_c* sender_name; + Private_c* priv = NULL; + + if (mail != NULL && Common_Get(now_private) != NULL && mail->header.sender.type == mMl_NAME_TYPE_PLAYER) { + sender_name = &mail->header.sender; + + if (mPr_NullCheckPersonalID(&sender_name->personalID) == FALSE) { + if (mPr_CheckCmpPersonalID(&sender_name->personalID, &Common_Get(now_private)->player_ID) == TRUE) { + priv = Common_Get(now_private); + } + else { + int priv_idx = mPr_GetPrivateIdx(&sender_name->personalID); + + if (priv_idx != -1) { + priv = Save_Get(private + priv_idx); + } + } + + if (priv != NULL) { + mActor_name_t present = mail->present; + + if (present != EMPTY_NO && present != RSV_NO) { + mMsm_record_c* record = &priv->museum_record; + + if (present == ITM_FOSSIL) { + u8 stored_fossils = record->stored_fossil_num; + + if (stored_fossils < mMsm_REMAIL_SLOTS) { + record->stored_fossil_num = stored_fossils + 1; + } + } + else { + mMsm_SetRemailInfo(&record->remail_info, priv, present); + record->remail_pending = TRUE; + } + } + } + } + } +} + +extern int mMsm_GetDepositAbleNum(mActor_name_t* fg_items, mCoBG_Collision_u* col_data) { + int depositable_num = 0; + int i; + + if (fg_items != NULL && col_data != NULL) { + for (i = 0; i < UT_TOTAL_NUM; i++) { + if (*fg_items == EMPTY_NO && mCoBG_CheckHole_OrgAttr(col_data->data.unit_attribute)) { + depositable_num++; + } + + fg_items++; + col_data++; + } + } + + return depositable_num; +} + +static int mMsm_GetDepositAbleNum_cancel(mActor_name_t* fg_items, mCoBG_Collision_u* col_data, u16* cancel_ut) { + int depositable_num = 0; + int ut_z; + + if (fg_items != NULL && col_data != NULL) { + for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) { + int ut_x; + for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) { + if ((((*cancel_ut) >> ut_x) & 1) != TRUE && *fg_items == EMPTY_NO && mCoBG_CheckHole_OrgAttr(col_data->data.unit_attribute)) { + depositable_num++; + } + + fg_items++; + col_data++; + } + + cancel_ut++; + } + } + + return depositable_num; +} + +extern void mMsm_DepositItemBlock_cancel(mActor_name_t* fg_items, mActor_name_t deposit_item, mCoBG_Collision_u* col_data, u16* deposit, u16* cancel_ut, u8 valid_ut_count) { + int deposit_idx = RANDOM(valid_ut_count); + int ut_z; + + for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) { + int ut_x; + + for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) { + if ((((*cancel_ut) >> ut_x) & 1) != TRUE && *fg_items == EMPTY_NO && mCoBG_CheckHole_OrgAttr(col_data->data.unit_attribute)) { + if (deposit_idx == 0) { + *fg_items = deposit_item; + ut_z = UT_Z_NUM; // break out of outer loop + *deposit |= (1 << ut_x); + break; + } + else { + deposit_idx--; + } + } + + fg_items++; + col_data++; + } + + deposit++; + cancel_ut++; + } +} + +extern void mMsm_DepositItemBlock(mActor_name_t* fg_items, mActor_name_t item, int block_x, int block_z, u16* deposit, u8 valid_ut_count) { + mCoBG_Collision_u* col_data = mFI_GetBkNum2ColTop(block_x, block_z); + int deposit_idx = RANDOM(valid_ut_count); + int ut; + + for (ut = 0; ut < UT_TOTAL_NUM; ut++) { + if (*fg_items == EMPTY_NO && mCoBG_CheckHole_OrgAttr(col_data->data.unit_attribute)) { + if (deposit_idx == 0) { + int ut_x = ut & (UT_X_NUM - 1); + int ut_z = ut >> 4; + + if (item != ITM_PITFALL) { + *fg_items = item; + deposit[ut_z] |= (1 << ut_x); + } + else { + int hole_num = mCoBG_BnumUnum2HoleNumber(block_x, block_z, ut_x, ut_z); + + if (hole_num != -1) { + *fg_items = BURIED_PITFALL0 + hole_num; + } + } + + break; + } + else { + deposit_idx--; + } + } + + fg_items++; + col_data++; + } +} + +static void mMsm_DepositFossilBlock(mActor_name_t* fg_items, mCoBG_Collision_u* col_data, u16* deposit, u16* cancel, u8 valid_ut_count) { + mMsm_DepositItemBlock_cancel(fg_items, ITM_FOSSIL, col_data, deposit, cancel, valid_ut_count); +} + +static void mMsm_DepositFossilBlockLine(int line, u16* cancel_ut) { + /* NOTE: line is a column (of Z-acres, for example the 1 column) */ + + int depositable_acres; + u8 depositable_line[FG_BLOCK_Z_NUM]; + u16* cancel_ut_p; + int block_x = line + 1; + int block_z; + + cancel_ut_p = cancel_ut; + depositable_acres = 0; + bzero(depositable_line, FG_BLOCK_Z_NUM * sizeof(u8)); + + for (block_z = 0; block_z < FG_BLOCK_Z_NUM; block_z++) { + int bad_acre = mFI_CheckBlockKind_OR( + block_x, block_z + 1, + mRF_BLOCKKIND_PLAYER | mRF_BLOCKKIND_SHRINE | mRF_BLOCKKIND_STATION | mRF_BLOCKKIND_POOL | mRF_BLOCKKIND_DUMP + ); + + if (bad_acre == FALSE) { + depositable_line[block_z] = mMsm_GetDepositAbleNum_cancel(Save_Get(fg[block_z][line]).items[0], mFI_GetBkNum2ColTop(block_x, block_z + 1), cancel_ut); + + if (depositable_line[block_z] != 0) { + depositable_acres++; + } + } + + cancel_ut += UT_Z_NUM * FG_BLOCK_X_NUM; + } + + if (depositable_acres > 0) { + int selected_z_acre; + + cancel_ut = cancel_ut_p; + selected_z_acre = RANDOM(depositable_acres); + + for (block_z = 0; block_z < FG_BLOCK_Z_NUM; block_z++) { + if (depositable_line[block_z] != 0) { + if (selected_z_acre == 0) { + mMsm_DepositFossilBlock(Save_Get(fg[block_z][line]).items[0], mFI_GetBkNum2ColTop(block_x, block_z + 1), Save_Get(deposit[line + block_z * FG_BLOCK_X_NUM]), cancel_ut, depositable_line[block_z]); + return; + } + else { + selected_z_acre--; + } + } + + cancel_ut += UT_Z_NUM * FG_BLOCK_X_NUM; + } + } +} + +extern int mMsm_RecordDepositFossil(u8* record, mActor_name_t item, int block_x) { + int res = FALSE; + + if (item == ITM_FOSSIL) { + *record |= (1 << block_x); + res = TRUE; + } + + return res; +} + +extern u8 mMsm_GetDepositBlockNum(u8 record) { + u8 deposit_block_num = 0; + int block_x; + + for (block_x = 0; block_x < FG_BLOCK_X_NUM; block_x++) { + if (((record >> (block_x + 1)) & 1) == TRUE) { + deposit_block_num++; + } + } + + return deposit_block_num; +} + +extern void mMsm_DepositFossil(u8 deposit_record, int fossil_count, u16* cancel_ut, int send_order_info) { + int deposit_count; + u16* cancel_ut_p = cancel_ut; + u8 already_deposited = mMsm_GetDepositBlockNum(deposit_record); + u8 available_blocks; + + if (fossil_count < mMsm_DEPOSIT_FOSSIL_MAX) { + deposit_count = mMsm_DEPOSIT_FOSSIL_MAX - fossil_count; + available_blocks = FG_BLOCK_X_NUM - already_deposited; + + while (deposit_count > 0 && available_blocks != 0) { + int selected_row; + int block_x; + + cancel_ut = cancel_ut_p; + selected_row = RANDOM(available_blocks); + + for (block_x = 0; block_x < FG_BLOCK_X_NUM; block_x++) { + if (((deposit_record >> (block_x + 1)) & 1) == FALSE) { + if (selected_row <= 0) { + mMsm_DepositFossilBlockLine(block_x, cancel_ut); + available_blocks--; + deposit_record |= (1 << (block_x + 1)); + break; + } + else { + selected_row--; + } + } + + cancel_ut += UT_Z_NUM; + } + + deposit_count--; + } + + if (send_order_info) { + mMsm_OrderInformationMail(); + } + } + + mMsm_SendResultMail(); + mMsm_SendInformationMail(); +} + +static void mMsm_SetPrivateCompMail(Private_c* priv, int flag) { + if (priv != NULL) { + priv->state_flags |= flag; + } +} + +static int mMsm_CheckSendCompMail() { + Private_c* priv = Save_Get(private); + int res = FALSE; + int i; + + for (i = 0; i < PLAYER_NUM; i++) { + if (mPr_NullCheckPersonalID(&priv->player_ID) == FALSE && (priv->state_flags & mPr_FLAG_MUSEUM_COMP_HANDBILL_SCHEDULED)) { + res = TRUE; + break; + } + + priv++; + } + + return res; +} + +static void mMsm_SetSendCompMail() { + Private_c* priv = Save_Get(private); + int i; + + for (i = 0; i < PLAYER_NUM; i++) { + if (mPr_NullCheckPersonalID(&priv->player_ID) == FALSE) { + mMsm_SetPrivateCompMail(priv, mPr_FLAG_MUSEUM_COMP_HANDBILL_SCHEDULED); + } + + priv++; + } +} + +extern void mMsm_SetCompMail() { + if ( + mMsm_CheckSendCompMail() == FALSE && + mMmd_CountDisplayedFossil() == mMmd_FOSSIL_NUM && + mMmd_CountDisplayedArt() == mMmd_ART_NUM && + mMmd_CountDisplayedInsect() == mMmd_INSECT_NUM && + mMmd_CountDisplayedFish() == mMmd_FISH_NUM + ) { + mMsm_SetSendCompMail(); + } +} + +extern void mMsm_SendCompMail() { + Private_c* priv = Save_Get(private); + int state_flags; + int i; + + for (i = 0; i < PLAYER_NUM; i++) { + state_flags = priv->state_flags; + if (mPr_NullCheckPersonalID(&priv->player_ID) == FALSE) { + /* Send completion letter & reward if scheduled but not yet received. */ + + if ( + (state_flags & mPr_FLAG_MUSEUM_COMP_HANDBILL_SCHEDULED) != 0 && + (state_flags & mPr_FLAG_MUSEUM_COMP_HANDBILL_RECEIVED) == 0 + ) { + int land_name_len = mMsg_Get_Length_String(Save_Get(land_info.name), LAND_NAME_SIZE); + + mHandbill_Set_free_str(mHandbill_FREE_STR0, Save_Get(land_info.name), land_name_len); + + if (mMl_send_mail_postoffice(&priv->player_ID, i, FTR_MUSEUM_MODEL, ITM_PAPER24, 0x22F, l_museum_name_str, mMl_DATA2, mMl_TYPE_MUSEUM) == TRUE) { + mMsm_SetPrivateCompMail(priv, mPr_FLAG_MUSEUM_COMP_HANDBILL_RECEIVED); + } + } + } + + priv++; + } +} diff --git a/rel/m_private.c b/rel/m_private.c index 4b76135f..a1bbb37e 100644 --- a/rel/m_private.c +++ b/rel/m_private.c @@ -148,7 +148,7 @@ extern void mPr_ClearPrivateInfo(Private_c* private_info) { mNpc_ClearRemail(&private_info->remail); mPr_ClearAnimalMemory(&private_info->animal_memory); mPr_ClearMapInfo(private_info->maps, mPr_FOREIGN_MAP_COUNT); - mMsm_ClearRecord(&private_info->museum_mail_info); + mMsm_ClearRecord(&private_info->museum_record); private_info->state_flags = 1; } @@ -735,7 +735,7 @@ extern s16 mPr_GetGoodsPower() { extern int mPr_CheckMuseumAddress(Private_c* priv) { int res = FALSE; - if (priv != NULL && priv->museum_mail_info.contacted) { + if (priv != NULL && priv->museum_record.contacted) { res = TRUE; } @@ -745,7 +745,7 @@ extern int mPr_CheckMuseumAddress(Private_c* priv) { extern int mPr_CheckMuseumInfoMail(Private_c* priv) { int res = FALSE; - if (priv != NULL && priv->museum_mail_info.send_info_mail) { + if (priv != NULL && priv->museum_record.send_info_mail) { res = TRUE; } @@ -790,7 +790,7 @@ extern int mPr_LoadPak_and_SetPrivateInfo2(Private_c* unused_private, u8 player_ house = Save_GetPointer(homes[mHS_get_arrange_idx(i)]); loan = priv->inventory.loan; - g_foreigner_private.museum_mail_info.contacted = priv->museum_mail_info.contacted; + g_foreigner_private.museum_record.contacted = priv->museum_record.contacted; mPr_CopyPrivateInfo(priv, &g_foreigner_private); if (mHm_CheckKeepHouseSize(i) == FALSE || house->size_info.next_size == mHm_HOMESIZE_STATUE) {