summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/6A5B00.h4
-rw-r--r--include/6A83A0.h2
-rw-r--r--include/6B8A70.h28
-rw-r--r--include/6C05A0.h8
-rw-r--r--include/6DA460.h5
-rw-r--r--include/6DB420.h110
-rw-r--r--include/6DE300.h74
-rw-r--r--include/6E30B0.h4
-rw-r--r--include/6E7AD0.h2
-rw-r--r--include/alignment.h1
-rw-r--r--include/code_variables.h4
-rw-r--r--include/lb_rtc.h2
-rw-r--r--include/libc64/malloc.h2
-rw-r--r--include/m_actor.h1
-rw-r--r--include/m_collision_bg.h2
-rw-r--r--include/m_common_data.h32
-rw-r--r--include/m_event.h2
-rw-r--r--include/m_field_info.h25
-rw-r--r--include/m_field_make.h29
-rw-r--r--include/m_handbill.h27
-rw-r--r--include/m_home.h8
-rw-r--r--include/m_item_name.h2
-rw-r--r--include/m_land.h24
-rw-r--r--include/m_mail.h98
-rw-r--r--include/m_mail_check.h10
-rw-r--r--include/m_name_table.h2
-rw-r--r--include/m_npc.h577
-rw-r--r--include/m_npc_base.h48
-rw-r--r--include/m_private.h126
-rw-r--r--include/m_private_internals.h51
-rw-r--r--include/m_quest.h116
-rw-r--r--include/m_submenu.h2
-rw-r--r--include/segment_symbols.h5
-rw-r--r--include/sys_math.h6
-rw-r--r--linker_scripts/jp/symbol_addrs_code.txt457
-rw-r--r--src/boot/libc64/malloc.c2
-rw-r--r--src/code/lb_rtc.c2
-rw-r--r--src/code/m_field_info.c20
-rw-r--r--src/code/m_mail.c108
-rw-r--r--src/code/m_npc.c3984
-rw-r--r--src/code/m_npc_walk.c6
-rw-r--r--src/code/m_start_data_init.c23
-rw-r--r--src/code/m_submenu.c2
-rw-r--r--src/overlays/actors/ovl_Npc/ac_npc.h8
-rw-r--r--src/overlays/gamestates/ovl_play/m_play.c2
-rw-r--r--yamls/jp/code.yaml6
46 files changed, 5165 insertions, 894 deletions
diff --git a/include/6A5B00.h b/include/6A5B00.h
index 6dab5c8..54cd3d5 100644
--- a/include/6A5B00.h
+++ b/include/6A5B00.h
@@ -22,9 +22,9 @@
// void func_80082910_jp();
// void func_800829D4_jp();
// void func_80082B4C_jp();
-// void func_80082BD8_jp();
+void func_80082BD8_jp(u16*, s32, s32, s32);
// void func_80082C30_jp();
-// void func_80082CC8_jp();
+s32 mEvNM_CheckJointEvent(u16);
// void func_80082DA0_jp();
// void func_80082E40_jp();
diff --git a/include/6A83A0.h b/include/6A83A0.h
index 803d3de..60c2823 100644
--- a/include/6A83A0.h
+++ b/include/6A83A0.h
@@ -16,7 +16,7 @@
// void func_80084CD8_jp();
// void func_80084D08_jp();
void func_80084DA4_jp(void);
-// void func_80084DE0_jp();
+s32 mFAs_GetFieldRank(void);
// void mFAs_PrintFieldAssessment();
#endif
diff --git a/include/6B8A70.h b/include/6B8A70.h
deleted file mode 100644
index 4f4a3d1..0000000
--- a/include/6B8A70.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef C_6B8A70_H
-#define C_6B8A70_H
-
-#include "ultra64.h"
-#include "unk.h"
-
-typedef struct LandName {
- /* 0x0 */ UNK_TYPE1 unk_0[0x6];
-} LandName; // size = 0x6
-
-// void func_80094DD0_jp();
-// void func_80094E10_jp();
-// void func_80094E38_jp();
-// void func_80094E90_jp();
-// void func_80094EE0_jp();
-void mLd_CopyLandName(LandName* arg0, LandName* arg1);
-// void func_80094F24_jp();
-// void func_80094F84_jp();
-// void func_8009504C_jp();
-// void func_800950D8_jp();
-// void func_800950E8_jp();
-// void func_8009519C_jp();
-// void mLd_PlayerManKindCheck();
-// void func_800951E4_jp();
-// void func_80095218_jp();
-void mLd_LandDataInit(void);
-
-#endif
diff --git a/include/6C05A0.h b/include/6C05A0.h
deleted file mode 100644
index 254df1d..0000000
--- a/include/6C05A0.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef C_6C05A0_H
-#define C_6C05A0_H
-
-#include "ultra64.h"
-
-// void func_8009C900_jp();
-
-#endif
diff --git a/include/6DA460.h b/include/6DA460.h
index 820a8aa..5593cd6 100644
--- a/include/6DA460.h
+++ b/include/6DA460.h
@@ -3,13 +3,14 @@
#include "ultra64.h"
+struct Mail_c;
struct Game_Play;
// void func_800B67C0_jp();
// void func_800B6838_jp();
-// void func_800B68E8_jp();
+s32 mPO_get_keep_mail_sum(void);
// void func_800B690C_jp();
-// void func_800B6A3C_jp();
+s32 mPO_receipt_proc(Mail_c*, s32);
// void func_800B6AC8_jp();
// void func_800B6B94_jp();
// void func_800B6C14_jp();
diff --git a/include/6DB420.h b/include/6DB420.h
deleted file mode 100644
index dddbf59..0000000
--- a/include/6DB420.h
+++ /dev/null
@@ -1,110 +0,0 @@
-#ifndef C_6DB420_H
-#define C_6DB420_H
-
-#include "ultra64.h"
-#include "6B8A70.h"
-#include "unk.h"
-
-struct PrivateInfo;
-struct mPr_map_info_c;
-struct LandInfo;
-struct MotherMailInfo;
-
-typedef struct PlayerName {
- /* 0x0 */ UNK_TYPE1 unk_0[0x6];
-} PlayerName; // size = 0x6
-
-typedef struct PersonalID {
- /* 0x0 */ PlayerName unk_0;
- /* 0x6 */ LandName unk_6;
- /* 0xC */ u16 unk_C;
- /* 0xE */ u16 unk_E;
-} PersonalID; // size = 0x10
-
-// void func_800B7780_jp();
-void mPr_CopyPlayerName(PlayerName* dst, PlayerName* src);
-// void func_800B77C4_jp();
-// void func_800B7804_jp();
-// void func_800B785C_jp();
-// void func_800B7914_jp();
-void mPr_ClearPersonalID(PersonalID* arg0);
-// void func_800B7998_jp();
-void mPr_CopyPersonalID(PersonalID* arg0, PersonalID* arg1);
-s32 mPr_CheckCmpPersonalID(PersonalID* arg0, PersonalID* arg1);
-// void func_800B7A94_jp();
-// void func_800B7AB0_jp();
-void mPr_ClearPrivateInfo(struct PrivateInfo* private);
-// void func_800B7B8C_jp();
-// void func_800B7BC0_jp();
-// void func_800B7CD0_jp();
-// void func_800B7D50_jp();
-void mPr_InitPrivateInfo(struct PrivateInfo* private);
-// void func_800B7F00_jp();
-// void func_800B7F48_jp();
-s32 mPr_CheckPrivate(struct PrivateInfo* private);
-// void func_800B7FA0_jp();
-// void func_800B7FD4_jp();
-// void func_800B8068_jp();
-// void func_800B80B4_jp();
-// void func_800B8128_jp();
-// void func_800B81A4_jp();
-// void func_800B8204_jp();
-// void func_800B828C_jp();
-// void func_800B8318_jp();
-// void func_800B83D4_jp();
-// void func_800B8544_jp();
-// void func_800B86EC_jp();
-// void func_800B88EC_jp();
-// void func_800B8A88_jp();
-void mPr_SetPossessionItem(struct PrivateInfo* priv, int idx, u16 item, u32 cond);
-// void func_800B8B8C_jp();
-// void func_800B8BE4_jp();
-// void func_800B8C10_jp();
-// void func_800B8C20_jp();
-// void func_800B8C34_jp();
-// void func_800B8C9C_jp();
-// void func_800B8D18_jp();
-// void func_800B8D3C_jp();
-s32 func_800B8D64_jp(u8 player_no, s32 arg1);
-void mPr_ClearMotherMailInfo(struct MotherMailInfo* arg0);
-// void func_800B8F20_jp();
-// void func_800B8FB8_jp();
-// void func_800B9038_jp();
-// void func_800B9170_jp();
-// void func_800B9350_jp();
-// void func_800B93AC_jp();
-// void func_800B947C_jp();
-// void func_800B94E0_jp();
-// void func_800B9704_jp();
-// void func_800B9790_jp();
-// void func_800B97C8_jp();
-// void func_800B97F8_jp();
-// void func_800B996C_jp();
-// void func_800B9AF0_jp();
-void func_800B9B2C_jp(void);
-// void func_800B9C34_jp();
-void mPr_SendForeingerAnimalMail(struct PrivateInfo* privateInfo);
-void mPr_StartSetCompleteTalkInfo(void);
-// void func_800B9E90_jp();
-// void func_800B9EB4_jp();
-// void func_800B9ED4_jp();
-// void func_800B9F00_jp();
-// void func_800B9F74_jp();
-// void func_800B9FA0_jp();
-// void func_800BA014_jp();
-// void func_800BA054_jp();
-// void func_800BA09C_jp();
-// void func_800BA0E4_jp();
-// void func_800BA130_jp();
-// void func_800BA150_jp();
-// void func_800BA18C_jp();
-// void func_800BA214_jp();
-// void func_800BA2B0_jp();
-// void func_800BA2D4_jp();
-// void func_800BA344_jp();
-// void func_800BA3D0_jp();
-void mPr_RenewalMapInfo(struct mPr_map_info_c* maps, s32 count, struct LandInfo* landInfo);
-// void mPr_RandomSetPlayerData_title_demo();
-// void mPr_PrintMapInfo_debug();
-
-#endif
diff --git a/include/6DE300.h b/include/6DE300.h
deleted file mode 100644
index 106f274..0000000
--- a/include/6DE300.h
+++ /dev/null
@@ -1,74 +0,0 @@
-#ifndef C_6DE300_H
-#define C_6DE300_H
-
-#include "ultra64.h"
-#include "unk.h"
-
-struct mQst_delivery_c;
-struct mQst_errand_c;
-struct mQst_not_saved_c;
-
-// void func_800BA660_jp();
-void mQst_ClearDelivery(struct mQst_delivery_c* deliveries, s32 count);
-void mQst_ClearErrand(struct mQst_errand_c* errands, s32 count);
-// void func_800BA778_jp();
-void mQst_ClearNotSaveQuest(struct mQst_not_saved_c* quest);
-// void func_800BA7E8_jp();
-// void func_800BA8A0_jp();
-// void func_800BA8F4_jp();
-// void func_800BAA10_jp();
-// void func_800BAA7C_jp();
-// void func_800BAAA4_jp();
-// void func_800BABE8_jp();
-// void func_800BAC84_jp();
-// void func_800BACEC_jp();
-// void func_800BADBC_jp();
-// void func_800BAE78_jp();
-UNK_RET mQst_CheckLimitbyPossessionIdx(s32 arg0);
-// void func_800BB0A8_jp();
-// void func_800BB0E8_jp();
-// void func_800BB10C_jp();
-// void func_800BB270_jp();
-// void func_800BB3A4_jp();
-// void func_800BB4B0_jp();
-// void func_800BB5DC_jp();
-// void func_800BB634_jp();
-// void func_800BB658_jp();
-// void func_800BB67C_jp();
-// void func_800BB6A0_jp();
-// void func_800BB6F0_jp();
-// void func_800BB740_jp();
-// void func_800BB86C_jp();
-// void func_800BB990_jp();
-// void func_800BBAB0_jp();
-// void func_800BBB30_jp();
-// void func_800BBBEC_jp();
-// void func_800BBCBC_jp();
-// void func_800BBD00_jp();
-// void func_800BBD68_jp();
-// void func_800BBD90_jp();
-// void func_800BBDE0_jp();
-// void func_800BBE78_jp();
-// void func_800BBEE0_jp();
-// void func_800BBF3C_jp();
-// void func_800BBF98_jp();
-// void func_800BC064_jp();
-// void func_800BC10C_jp();
-// void func_800BC12C_jp();
-// void func_800BC14C_jp();
-// void func_800BC1E4_jp();
-// void func_800BC28C_jp();
-// void func_800BC33C_jp();
-// void func_800BC368_jp();
-// void func_800BC394_jp();
-// void func_800BC414_jp();
-// void func_800BC454_jp();
-// void func_800BC528_jp();
-// void func_800BC5D4_jp();
-// void func_800BC6B0_jp();
-// void func_800BC724_jp();
-// void func_800BC830_jp();
-// void mQst_PrintQuestInfo();
-
-
-#endif
diff --git a/include/6E30B0.h b/include/6E30B0.h
index 41c50a4..e08b2b8 100644
--- a/include/6E30B0.h
+++ b/include/6E30B0.h
@@ -20,7 +20,7 @@ struct Game;
// void func_800BFAA8_jp();
// void func_800BFC00_jp();
// void func_800BFC5C_jp();
-// void func_800BFCF0_jp();
+void mSP_SelectRandomItem_New(Game*, u16*, s32, u16*, s32, s32, s32);
// void func_800BFF8C_jp();
// void func_800BFFC0_jp();
// void func_800C0194_jp();
@@ -71,7 +71,7 @@ void mSP_ExchangeLineUp_InGame(struct Game* game);
// void func_800C2578_jp();
// void func_800C2718_jp();
// void func_800C284C_jp();
-// void func_800C297C_jp();
+void mSP_RandomUmbSelect(u16*, s32);
// void func_800C2AAC_jp();
// void func_800C2B70_jp();
// void func_800C2CC8_jp();
diff --git a/include/6E7AD0.h b/include/6E7AD0.h
index 06b9645..00d74f5 100644
--- a/include/6E7AD0.h
+++ b/include/6E7AD0.h
@@ -4,7 +4,7 @@
#include "ultra64.h"
// void func_800C3E30_jp();
-void func_800C3F70_jp(u8* buffer, s32 buffer_len, s32 arg2);
+void mString_Load_StringFromRom(char* buffer, s32 buffer_len, s32 arg2);
// void func_800C4084_jp();
// void func_800C40F8_jp();
// void func_800C4168_jp();
diff --git a/include/alignment.h b/include/alignment.h
index 9fb3b57..5ab84ac 100644
--- a/include/alignment.h
+++ b/include/alignment.h
@@ -3,6 +3,7 @@
#include "attributes.h"
+#define ALIGN2(val) (((val) + 1) & ~1)
#define ALIGN4(val) (((val) + 3) & ~3)
#define ALIGN8(val) (((val) + 7) & ~7)
#define ALIGN16(val) (((val) + 0xF) & ~0xF)
diff --git a/include/code_variables.h b/include/code_variables.h
index 526347a..455a8db 100644
--- a/include/code_variables.h
+++ b/include/code_variables.h
@@ -537,7 +537,6 @@ extern s32 CanLookGokiCount;
// extern UNK_TYPE D_8010AECC_jp;
// extern UNK_TYPE D_8010AEE0_jp;
// extern UNK_TYPE D_8010AEF4_jp;
-// extern UNK_TYPE D_8010AF58_jp;
// extern UNK_TYPE D_8010B034_jp;
// extern UNK_TYPE D_8010B074_jp;
// extern UNK_TYPE D_8010B078_jp;
@@ -564,7 +563,6 @@ extern s32 CanLookGokiCount;
// extern UNK_TYPE D_8010B4FC_jp;
// extern UNK_TYPE D_8010B500_jp;
// extern UNK_TYPE D_8010B504_jp;
-// extern UNK_TYPE D_8010B510_jp;
// extern UNK_TYPE D_8010B810_jp;
// extern UNK_TYPE D_8010B818_jp;
// extern UNK_TYPE D_8010B81C_jp;
@@ -1882,12 +1880,10 @@ extern MtxF MtxF_clear;
// extern UNK_TYPE B_80142BBE_jp;
// extern UNK_TYPE B_80142BC0_jp;
// extern UNK_TYPE B_80142BE0_jp;
-// extern UNK_TYPE B_80142C00_jp;
// extern UNK_TYPE B_80142CF0_jp;
// extern UNK_TYPE B_80142D08_jp;
// extern UNK_TYPE B_80142E38_jp;
// extern UNK_TYPE B_80142E58_jp;
-// extern UNK_TYPE B_80142E78_jp;
// extern UNK_TYPE B_80142E80_jp;
// extern UNK_TYPE B_80142E98_jp;
// extern UNK_TYPE B_80142EB8_jp;
diff --git a/include/lb_rtc.h b/include/lb_rtc.h
index 1394b30..594f979 100644
--- a/include/lb_rtc.h
+++ b/include/lb_rtc.h
@@ -116,7 +116,7 @@ s32 lbRTC_IsOverTime(const lbRTC_time_c* t0, const lbRTC_time_c* t1);
s32 lbRTC_IsJustAtRTC(const lbRTC_time_c* time, s32 flags);
s32 lbRTC_IsOverRTC(const lbRTC_time_c* time);
s32 lbRTC_IsOverWeekRTC(const lbRTC_time_c* t0, lbRTC_weekday_t week);
-void func_800D5480_jp(lbRTC_time_c* t0, lbRTC_time_c* t1);
+s32 lbRTC_IntervalTime(lbRTC_time_c* t0, lbRTC_time_c* t1);
s32 lbRTC_GetIntervalDays(const lbRTC_time_c* t0, const lbRTC_time_c* t1);
void lbRTC_Add_YY(lbRTC_time_c* time, s32 years);
void lbRTC_Add_MM(lbRTC_time_c* time, s32 month);
diff --git a/include/libc64/malloc.h b/include/libc64/malloc.h
index 3ebbb4d..9de623c 100644
--- a/include/libc64/malloc.h
+++ b/include/libc64/malloc.h
@@ -9,7 +9,7 @@ void* malloc(size_t size);
void* malloc_r(size_t size);
void* realloc(void* ptr, size_t size);
void free(void* ptr);
-void* calloc(s32 num, size_t size);
+void* calloc(size_t num, size_t size);
void GetFreeArena(size_t* outMaxFree, size_t* outFree, size_t* outAlloc);
s32 CheckArena(void);
void MallocInit(void* heap, size_t size);
diff --git a/include/m_actor.h b/include/m_actor.h
index 1293e10..1c08512 100644
--- a/include/m_actor.h
+++ b/include/m_actor.h
@@ -41,6 +41,7 @@ typedef enum ActorFootIndex {
// TODO: figure out if those values make sense as an enum or if they should be changed to defines
typedef enum FgNameF000 {
/* 0x0 */ FGNAME_F000_0 = 0x0,
+ /* 0x0 */ FGNAME_F000_1 = 0x1,
/* 0x5 */ FGNAME_F000_5 = 0x5,
/* 0x8 */ FGNAME_F000_8 = 0x8,
/* 0xD */ FGNAME_F000_D = 0xD,
diff --git a/include/m_collision_bg.h b/include/m_collision_bg.h
index 182ebf3..7f03174 100644
--- a/include/m_collision_bg.h
+++ b/include/m_collision_bg.h
@@ -211,7 +211,7 @@ f32 mCoBG_GetBgY_OnlyCenter_FromWpos2(xyz_t arg0, f32 arg1);
// void func_80072398_jp();
// void func_800723C4_jp();
// void func_80072418_jp();
-// void func_8007244C_jp();
+s32 func_8007244C_jp(u32);
// void func_8007246C_jp();
// void func_8007249C_jp();
// void func_80072530_jp();
diff --git a/include/m_common_data.h b/include/m_common_data.h
index 6ea9d1d..6ccff3d 100644
--- a/include/m_common_data.h
+++ b/include/m_common_data.h
@@ -101,10 +101,6 @@ typedef struct CommonData_unk_10098 {
/* 0x86C */ UNK_TYPE unk_86C;
} CommonData_unk_10098; // size >= 0x870
-typedef struct MotherMailInfo {
- /* 0x00 */ UNK_TYPE1 unk_00[0xE];
-} MotherMailInfo; // size = 0xE
-
typedef enum Season {
/* 0 */ SPRING,
/* 1 */ SUMMER,
@@ -171,23 +167,27 @@ typedef struct CommonData {
/* 0x062A8 */ Foreground foreground[FG_BLOCK_Z_NUM][FG_BLOCK_X_NUM];
/* 0x09EA8 */ u8 unk_09EA8[0x70];
/* 0x09F18 */ Animal_c animals[ANIMAL_NUM_MAX]; // villagers in town
- /* 0x0EC70 */ u8 unk_0EC70[0x134];
+ /* 0x0EC70 */ AnmPersonalID_c lastRemovedAnimalId;
+ /* 0x0EC7C */ u8 unk_0EC7C[0x128];
/* 0x0EDA4 */ EventSaveInfo eventSaveInfo;
/* 0x0EE40 */ u8 unk_0EE40[0x118];
/* 0x0EF58 */ u16 fruit;
/* 0x0EF5A */ UNK_TYPE1 unk_0EF5A[0x12];
- /* 0x0EF6C */ Mail unk_0EF6C[5];
+ /* 0x0EF6C */ Mail_c unk_0EF6C[5];
/* 0x0F2A0 */ UNK_TYPE1 unk_0F2A0[0x17C];
/* 0x0F41C */ SnowmanData snowmanData[SNOWMAN_SAVE_COUNT];
- /* 0x0F428 */ UNK_TYPE1 unk_F428[0x10];
+ /* 0x0F428 */ u64 melody;
+ /* 0x0F430 */ UNK_TYPE1 unk_F430[0x8];
/* 0x0F438 */ u8 stationType;
/* 0x0F439 */ u8 unk_F439[0x3];
/* 0x0F43C */ u16 deposit[FG_BLOCK_X_NUM * FG_BLOCK_Z_NUM][UT_Z_NUM]; // flags for which items are buried around town
- /* 0x0F7FC */ lbRTC_time_c unk_0F7FC;
- /* 0x0F804 */ MotherMailInfo motherMailInfo[PLAYER_NUM];
+ /* 0x0F7FC */ lbRTC_time_c lastGrowTime;
+ /* 0x0F804 */ PrivateMotherMail motherMailInfo[PLAYER_NUM];
/* 0x0F83C */ u8 unk_0F83C[0x8];
/* 0x0F844 */ FamicomEmuCommonData famicomEmuCommonData;
- /* 0x0F86A */ u8 unk_0F86A[0x32];
+ /* 0x0F86A */ UNK_TYPE1 unk_0F86A[0x2];
+ /* 0x0F86C */ u8 npcUsedTable[32];
+ /* 0x0F88C */ UNK_TYPE1 unk_0F88A[0x10];
/* 0x0F89C */ lbRTC_time_c unk_0F89C;
/* 0x0F8A4 */ lbRTC_time_c unk_0F8A4;
/* 0x0F8AC */ UNK_TYPE1 unk_0F8AC;
@@ -236,7 +236,7 @@ typedef struct CommonData {
/* 0x105A0 */ u32 sceneFromTitleDemo;
/* 0x105A4 */ NpsSchedule npcSchedule[ANIMAL_NUM_MAX];
/* 0x10694 */ NpcWalking npcWalk;
- /* 0x10710 */ UNK_TYPE1 unk_10710[0x3C];
+ /* 0x10710 */ NpcEvent npcEvent[5];
/* 0x1074C */ UNK_TYPE unk_1074C;
/* 0x10750 */ UNK_TYPE1 unk_10750[0x4];
/* 0x10754 */ UNK_TYPE unk_10754;
@@ -244,11 +244,13 @@ typedef struct CommonData {
/* 0x107A0 */ UNK_TYPE unk_107A0;
/* 0x107A4 */ UNK_TYPE1 unk_107A4[0x12];
/* 0x107B6 */ s16 unk_107B6; // named "demo_profile" in AC GCN decomp (though it's an array of two s16s in that game)
- /* 0x107B8 */ u8 unk_107B8[0x28];
+ /* 0x107B8 */ UNK_TYPE1 unk_107B8[0x28];
/* 0x107E0 */ s8 player_decoy_flag;
- /* 0x107E1 */ u8 unk_107E1[0x3];
+ /* 0x107E1 */ UNK_TYPE1 unk_107E1[0x3];
/* 0x107E4 */ s16 unk_107E4;
- /* 0x107E6 */ u8 unk_107E6[0x254];
+ /* 0x107E6 */ UNK_TYPE1 unk107E6[0x252];
+ /* 0x10A38 */ s8 beeStingFlag;
+ /* 0x10A39 */ UNK_TYPE1 unk_10A39[0x1];
/* 0x10A3A */ u8 gokiShockedFlag;
/* 0x10A3B */ UNK_TYPE1 unk_10A3B[0x1];
/* 0x10A3C */ UNK_TYPE1 unk_10A3C[0x2C];
@@ -257,7 +259,7 @@ typedef struct CommonData {
/* 0x10A6C */ UNK_TYPE1 unk_10A6C[0x14];
/* 0x10A80 */ UNK_TYPE1 unk_10A80[0x2];
/* 0x10A82 */ s16 unk_10A82;
- /* 0x10A84 */ u8 unk_10A84[0x2C];
+ /* 0x10A84 */ UNK_TYPE1 unk_10A84[0x2C];
/* 0x10AB0 */ u8 unk_10AB0; // named "pad_connected" in AC GCN decomp
/* 0x10AB1 */ UNK_TYPE1 unk_10AB1[0x7];
} CommonData; // size = 0x10AB8
diff --git a/include/m_event.h b/include/m_event.h
index 4731cea..8a13010 100644
--- a/include/m_event.h
+++ b/include/m_event.h
@@ -116,7 +116,7 @@ s32 mEv_check_status(s32, s16);
// void func_80080040_jp();
// void func_80080080_jp();
// void func_80080200_jp();
-// void func_8008033C_jp();
+u8* func_8008033C_jp(s32,s32);
// void func_800804AC_jp();
// void func_800806A0_jp();
// void func_800807E0_jp();
diff --git a/include/m_field_info.h b/include/m_field_info.h
index f199bf0..da6a455 100644
--- a/include/m_field_info.h
+++ b/include/m_field_info.h
@@ -5,7 +5,10 @@
#include "z64math.h"
#include "m_collision_bg.h"
+struct Actor;
struct Game_Play;
+struct FieldMakeBlockInfo;
+struct FieldMakeMoveActor;
typedef enum FieldType {
/* 0 */ FI_FIELDTYPE_FG,
@@ -36,7 +39,7 @@ typedef enum FieldRoom {
// void func_80087C30_jp();
// void func_80087C40_jp();
-// void func_80087C64_jp();
+struct FieldMakeBlockInfo* mFI_GetBlockTopP(void);
u16 mFI_GetFieldId(void);
// void func_80087C9C_jp();
// void func_80087D30_jp();
@@ -58,14 +61,14 @@ u16 mFI_GetFieldId(void);
// void func_800884E0_jp();
// void func_800885A8_jp();
s32 mFI_Wpos2BlockNum(s32*, s32*, xyz_t);
-// void func_80088780_jp();
+s32 mFI_Wpos2BkandUtNuminBlock(s32*,s32*, s32* ,s32* ,xyz_t);
// void func_8008883C_jp();
// void func_800888AC_jp();
// void func_80088938_jp();
// void func_800889D8_jp();
// void func_80088A58_jp();
// void func_80088B3C_jp();
-// void func_80088BC0_jp();
+void mFI_UtNum2PosXZInBk(f32*, f32*, s32,s32);
// void func_80088BFC_jp();
// void func_80088C74_jp();
// void func_80088CBC_jp();
@@ -92,7 +95,7 @@ u8 mFI_BkNum2BlockType(s32,s32);
// void func_80089404_jp();
void mFI_BlockKind2BkNum(s32*,s32*,s32);
// void func_800894D0_jp();
-mCoBG_unkStructUnion* func_80089538_jp(s32 arg0, s32 arg1);
+mCoBG_unkStructUnion* mFI_GetBkNum2ColTop(s32 arg0, s32 arg1);
// void func_800895B8_jp();
// void func_80089698_jp();
// void func_80089704_jp();
@@ -111,7 +114,7 @@ mCoBG_unkStructUnion* func_80089538_jp(s32 arg0, s32 arg1);
// void func_80089E84_jp();
// void func_80089EF8_jp();
// void func_8008A000_jp();
-// void func_8008A33C_jp();
+u16* mFI_BkNumtoUtFGTop(s32,s32);
// void func_8008A3BC_jp();
// void func_8008A410_jp();
// void func_8008A4F8_jp();
@@ -151,11 +154,11 @@ s32 func_8008B3E8_jp(xyz_t* arg0, UNK_TYPE arg1);
// void func_8008BAEC_jp();
// void func_8008BB64_jp();
// void func_8008BBF0_jp();
-// void func_8008BC64_jp();
+void mFI_SetMoveActorBitData_ON(s16, u8,u8);
// void func_8008BCFC_jp();
-// void func_8008BD98_jp();
+void mFI_MyMoveActorBitData_ON(struct Actor*);
// void func_8008BDCC_jp();
-// void func_8008BE00_jp();
+s32 func_8008BE00_jp(struct FieldMakeMoveActor*, s32);
// void func_8008BE38_jp();
// void func_8008BF34_jp();
// void func_8008BFC4_jp();
@@ -163,14 +166,14 @@ s32 func_8008B3E8_jp(xyz_t* arg0, UNK_TYPE arg1);
s32 mFI_CheckPlayerWade(s32);
// void func_8008C120_jp();
// void func_8008C130_jp();
-// void func_8008C1E0_jp();
+u16* mFI_GetDepositP(s32,s32);
// void func_8008C344_jp();
// void func_8008C390_jp();
// void func_8008C3B0_jp();
// void func_8008C3D4_jp();
// void func_8008C3E8_jp();
// void func_8008C458_jp();
-void func_8008C478_jp(u16* deposit, int ut_x, int ut_z);
+void mFI_BlockDepositOFF(u16* deposit, int ut_x, int ut_z);
// void func_8008C498_jp();
// void func_8008C4B8_jp();
// void func_8008C504_jp();
@@ -205,7 +208,7 @@ void mFI_Wpos2DepositOFF(xyz_t);
// void func_8008D3A4_jp();
// void func_8008D574_jp();
// void func_8008D6E0_jp();
-// void func_8008D7B0_jp();
+s32 func_8008D7B0_jp(u16);
// void func_8008D884_jp();
s32 mFI_GetWaveUtinBlock(s32* arg0, s32* arg1, s32 arg2, s32 arg3);
// void func_8008DA4C_jp();
diff --git a/include/m_field_make.h b/include/m_field_make.h
index 9222fee..3d2777b 100644
--- a/include/m_field_make.h
+++ b/include/m_field_make.h
@@ -19,9 +19,34 @@ struct Game;
#define UT_TOTAL_NUM (UT_X_NUM * UT_Z_NUM)
typedef struct Foreground {
- /* 0x000 */ u16 items[UT_Z_NUM][UT_X_NUM];
+ /* 0x000 */ u16 items[UT_Z_NUM][UT_X_NUM];
} Foreground; // size = 0x200
+typedef struct FieldMakeMoveActor {
+ /* 0x0 */ u16 nameId;
+ /* 0x2 */ s8 utX;
+ /* 0x3 */ s8 utZ;
+ /* 0x4 */ s8 npcId;
+ /* 0x6 */ s16 arg;
+} FieldMakeMoveActor; // size = 0x8
+
+typedef struct FieldMakeFGData {
+ /* 0x000 */ u16 id;
+ /* 0x002 */ u16 items[UT_Z_NUM][UT_X_NUM];
+ /* 0x202 */ UNK_TYPE1 unk_202[4];
+} FieldMakeFGData; // size = 0x206
+
+typedef struct FieldMakeFGInfo {
+ /* 0x00 */ u16 fgId;
+ /* 0x04 */ u16* itemsPtr;
+ /* 0x08 */ UNK_TYPE1 unk_08[0x8C];
+} FieldMakeFGInfo; // size = 0x94
+
+typedef struct FieldMakeBlockInfo {
+ /* 0x000 */ UNK_TYPE1 unk_000[0x580];
+ /* 0x580 */ FieldMakeFGInfo fgInfo;
+} FieldMakeBlockInfo; // size = 0x614
+
// void func_80084ED0_jp();
// void func_80084FAC_jp();
// void func_800850E4_jp();
@@ -63,6 +88,6 @@ void mFM_InitFgCombiSaveData(struct Game* game);
// void func_80087788_jp();
// void func_800877CC_jp();
void mFM_RenewalReserve(void);
-// void func_800879B0_jp();
+u16 mFM_GetReseveName(s32,s32);
#endif
diff --git a/include/m_handbill.h b/include/m_handbill.h
index ab691a7..7bf4641 100644
--- a/include/m_handbill.h
+++ b/include/m_handbill.h
@@ -6,6 +6,24 @@
struct Game;
struct Game_Play;
+
+typedef struct HandbillzInfo {
+ /* 0x00 */ u8* superBuf;
+ /* 0x04 */ size_t superBufSize;
+ /* 0x08 */ u8* mailBuf;
+ /* 0x0C */ size_t mailBufSize;
+ /* 0x10 */ u8* psBuf;
+ /* 0x14 */ size_t psBufSize;
+ /* 0x18 */ s32 superNo;
+ /* 0x1C */ s32 mailANo;
+ /* 0x20 */ s32 mailBNo;
+ /* 0x24 */ s32 mailCNo;
+ /* 0x28 */ s32 psNo;
+ /* 0x2C */ s32 headerBackStart;
+} HandbillzInfo; // size = 0x30
+
+
+//TODO: move these out of the handbill header
void Balloon_init(struct Game_Play* game_play);
void Balloon_move(struct Game_Play* game_play);
// void func_80092B7C_jp();
@@ -13,7 +31,8 @@ void Balloon_move(struct Game_Play* game_play);
// void func_80092BA0_jp();
// void func_80092BE8_jp();
void mHsRm_GetHuusuiRoom(struct Game* game_play, s32 player_no);
-// void func_80092D10_jp();
+
+void mHandbill_Set_free_str(s32, char*, s32);
// void func_80092E14_jp();
// void func_80092E80_jp();
// void func_80092FC4_jp();
@@ -47,13 +66,13 @@ void mHsRm_GetHuusuiRoom(struct Game* game_play, s32 player_no);
// void func_80093B28_jp();
// void func_80093C98_jp();
// void func_80093DA8_jp();
-// void func_80093F04_jp();
-// void func_80093F54_jp();
+void mHandbill_Load_HandbillFromRom(u8*, s32*, u8*, u8*, s32);
+void mHandbill_Load_HandbillFromRom2(u8*, s32, s32*, u8*, s32, u8*, s32);
// void func_80093F94_jp();
// void func_800940A8_jp();
// void func_800941B0_jp();
// void func_800942A0_jp();
// void func_80094400_jp();
-// void func_800944B8_jp();
+s32 mHandbillz_load(HandbillzInfo*);
#endif
diff --git a/include/m_home.h b/include/m_home.h
index 787b447..0fb873d 100644
--- a/include/m_home.h
+++ b/include/m_home.h
@@ -2,9 +2,10 @@
#define M_HOME_H_H
#include "ultra64.h"
-#include "6DB420.h"
#include "unk.h"
#include "lb_rtc.h"
+#include "m_private_internals.h"
+#include "m_mail.h"
#define HOME_MAILBOX_SIZE 10
#define HANIWA_ITEM_HOLD_NUM 4
@@ -57,12 +58,13 @@ typedef struct mHm_goki_c {
} mHm_goki_c; // size = 0x6
typedef struct mHm_hs_c {
- /* 0x000 */ PersonalID unk_000;
+ /* 0x000 */ PersonalID_c ownerID;
/* 0x010 */ UNK_TYPE1 unk_010[0x12];
/* 0x022 */ u8 unk_022;
/* 0x023 */ UNK_TYPE1 unk023[0x1];
/* 0x024 */ u8 unk_024;
- /* 0x025 */ UNK_TYPE1 unk025[0xABB];
+ /* 0x025 */ UNK_TYPE1 unk025[0x453];
+ /* 0x478 */ Mail_c mailbox[HOME_MAILBOX_SIZE];
/* 0xAE0 */ Haniwa_c haniwa;
/* 0xB3C */ mHm_goki_c goki;
/* 0xB42 */ UNK_TYPE1 unkB42[0x6];
diff --git a/include/m_item_name.h b/include/m_item_name.h
index c8c9bf4..a4d4a9b 100644
--- a/include/m_item_name.h
+++ b/include/m_item_name.h
@@ -4,6 +4,6 @@
#include "ultra64.h"
// void func_80096710_jp();
-// void func_80096740_jp();
+void mIN_copy_name_str(char*, u16);
#endif
diff --git a/include/m_land.h b/include/m_land.h
index 2cfab06..9b2af3a 100644
--- a/include/m_land.h
+++ b/include/m_land.h
@@ -8,7 +8,27 @@
#define LAND_NAME_MURA_SIZE (LAND_NAME_SIZE + 2)
typedef struct LandInfo {
- char unk00[0xA];
-} LandInfo; // size >= 0xA
+ /* 0x0 */char name[LAND_NAME_SIZE];
+ /* 0x6 */s8 exists;
+ /* 0x8 */u16 id;
+} LandInfo; // size = 0xA
+
+// void func_80094DD0_jp();
+// void func_80094E10_jp();
+s32 mLd_CheckCmpLandName(char* name1, char* name2);
+s32 mLd_CheckCmpLand(char* name1, u16 id1, char* name2, u16 id2);
+void mLd_ClearLandName(char* name);
+void mLd_CopyLandName(char* arg0, char* arg1);
+// void func_80094F24_jp();
+// void func_80094F84_jp();
+// void func_8009504C_jp();
+char* mLd_GetLandName(void);
+// void func_800950E8_jp();
+// void func_8009519C_jp();
+s32 mLd_PlayerManKindCheck(void);
+s32 mLd_CheckThisLand(char* arg0, u16 arg1);
+// void func_80095218_jp();
+void mLd_LandDataInit(void);
+
#endif
diff --git a/include/m_mail.h b/include/m_mail.h
index cbb9fdd..59473f0 100644
--- a/include/m_mail.h
+++ b/include/m_mail.h
@@ -2,26 +2,24 @@
#define M_MAIL_H
#include "ultra64.h"
-#include "6B8A70.h"
-#include "6DB420.h"
#include "unk.h"
+#include "m_private_internals.h"
+#include "m_npc_base.h"
-struct struct_func_8085CE18_jp_arg4;
+#define MAIL_HEADER_LEN (16 - PLAYER_NAME_LEN)
+#define MAIL_FOOTER_LEN 16
+#define MAIL_BODY_LEN 96
+
+#define MAIL_FOOTER2_LEN 26
+#define MAIL_HEADER2_LEN (MAIL_FOOTER2_LEN - PLAYER_NAME_LEN)
-// TODO: move to a better header
-typedef struct mMl_get_npcinfo_from_mail_name_arg0 {
- /* 0x0 */ u16 unk_0;
- /* 0x2 */ u16 unk_2;
- /* 0x4 */ LandName unk_4;
- /* 0xA */ u8 unk_A;
- /* 0xB */ u8 unk_B;
- /* 0xB */ u8 unk_C;
-} mMl_get_npcinfo_from_mail_name_arg0; // size >= 0xC
+struct struct_func_8085CE18_jp_arg4;
+struct AnmPersonalID_c;
// MailName?
typedef struct mMl_unk_00 {
- /* 0x00 */ PersonalID unk_00;
- /* 0x10 */ u8 unk_10;
+ /* 0x00 */ PersonalID_c personalID;
+ /* 0x10 */ u8 type;
} mMl_unk_00; // size = 0x12
typedef struct mMl_unk_2A {
@@ -35,41 +33,57 @@ typedef struct MailHeaderCommon {
/* 0x0C */ u8 unk_0C[16];
} MailHeaderCommon; //size = 0x1C
-// MailBox?
-typedef struct Mail {
- /* 0x00 */ mMl_unk_00 unk_00;
- /* 0x12 */ mMl_unk_00 unk_12;
- /* 0x24 */ UNK_TYPE1 unk_24[0x2];
- /* 0x26 */ u8 unk_26;
- /* 0x27 */ UNK_TYPE1 unk_27[0x1];
- /* 0x28 */ u8 unk_28;
- /* 0x29 */ u8 unk_29;
- /* 0x2A */ mMl_unk_2A unk_2A;
-} Mail; // size = 0xA4
+typedef struct MailHeader {
+ /* 0x00 */ mMl_unk_00 recipient;
+ /* 0x12 */ mMl_unk_00 sender;
+} MailHeader; // size = 0x24
+
+typedef struct MailContent {
+ /* 0x00 */ u8 font;
+ /* 0x01 */ u8 headerBackStart;
+ /* 0x02 */ u8 mailType;
+ /* 0x03 */ u8 paperType;
+ /* 0x04 */ u8 header[MAIL_HEADER_LEN];
+ /* 0x1C */ u8 body[MAIL_BODY_LEN];
+ /* 0xDC */ u8 footer[MAIL_FOOTER_LEN];
+} MailContent; // size = 0x7F
+
+typedef struct Mail_c {
+ /* 0x000 */ MailHeader header;
+ /* 0x024 */ u16 present;
+ /* 0x026 */ MailContent content;
+} Mail_c; //size = 0xA4
+
+typedef enum MailNameType {
+ /* 0 */ MAIL_NAME_TYPE_PLAYER,
+ /* 1 */ MAIL_NAME_TYPE_NPC,
+ /* 2 */ MAIL_NAME_NUM,
+ /* 255 */ MAIL_NAME_TYPE_CLEAR = 0xFF
+} MailNameType;
s32 mMl_strlen(const char* arg0, s32 size, char c);
s32 mMl_strlen2(s32* arg0, const char* arg1, s32 size, char c);
void mMl_strcpy_back(char* dst, const char* src, s32 size);
-void mMl_clear_mail_header(Mail* mail);
-void mMl_clear_mail(Mail* mail);
-void mMl_clear_mail_box(Mail* mail, s32 arg1);
-s32 mMl_check_not_used_mail(Mail* mail);
+void mMl_clear_mail_header(Mail_c* mail);
+void mMl_clear_mail(Mail_c* mail);
+void mMl_clear_mail_box(Mail_c* mail, s32 arg1);
+s32 mMl_check_not_used_mail(Mail_c* mail);
void mMl_copy_header_name(mMl_unk_00* arg0, mMl_unk_00* arg1);
-void mMl_set_from_name(Mail* arg0, Mail* arg1);
-void mMl_set_to_name(Mail* arg0, Mail* arg1);
-void mMl_set_to_plname(Mail* arg0, Mail* arg1);
-void mMl_set_playername(Mail* mail, PersonalID* arg1);
-void mMl_init_mail(Mail* mail, PersonalID* arg1);
-s32 mMl_chk_mail_free_space(Mail mail[], s32 arg1);
-s32 mMl_use_mail_space(Mail mail[], s32 arg1, PersonalID* arg2);
-s32 mMl_count_use_mail_space(Mail mail[], s32 arg1);
-void mMl_copy_mail(Mail* dst, Mail* src);
+void mMl_set_from_name(Mail_c* arg0, Mail_c* arg1);
+void mMl_set_to_name(Mail_c* arg0, Mail_c* arg1);
+void mMl_set_to_plname(Mail_c* arg0, Mail_c* arg1);
+void mMl_set_playername(Mail_c* mail, PersonalID_c* arg1);
+void mMl_init_mail(Mail_c* mail, PersonalID_c* arg1);
+s32 mMl_chk_mail_free_space(Mail_c mail[], s32 arg1);
+s32 mMl_use_mail_space(Mail_c mail[], s32 arg1, PersonalID_c* arg2);
+s32 mMl_count_use_mail_space(Mail_c mail[], s32 arg1);
+void mMl_copy_mail(Mail_c* dst, Mail_c* src);
void mMl_clear_mail_header_common(MailHeaderCommon* arg0);
void mMl_copy_mail_header_common(MailHeaderCommon* arg0, MailHeaderCommon* arg1);
-void mMl_set_mail_name_npcinfo(mMl_unk_00* arg0, mMl_get_npcinfo_from_mail_name_arg0* arg1);
-s32 mMl_get_npcinfo_from_mail_name(mMl_get_npcinfo_from_mail_name_arg0* arg0, mMl_unk_00* arg1);
-s32 mMl_hunt_for_send_address(Mail* mail);
+void mMl_set_mail_name_npcinfo(mMl_unk_00* arg0, AnmPersonalID_c* arg1);
+s32 mMl_get_npcinfo_from_mail_name(AnmPersonalID_c* arg0, mMl_unk_00* arg1);
+s32 mMl_hunt_for_send_address(Mail_c* mail);
s32 mMl_check_send_mail(struct struct_func_8085CE18_jp_arg4* arg0);
-s32 mMl_check_set_present_myself(Mail* mail);
+s32 mMl_check_set_present_myself(Mail_c* mail);
#endif
diff --git a/include/m_mail_check.h b/include/m_mail_check.h
new file mode 100644
index 0000000..7e26bf5
--- /dev/null
+++ b/include/m_mail_check.h
@@ -0,0 +1,10 @@
+#ifndef M_MAIL_CHECK_H
+#define M_MAIL_CHECK_H
+
+#include "ultra64.h"
+
+struct Game;
+
+s32 mMC_get_mail_hit_rate(s32*, u8*, struct Game*);
+
+#endif
diff --git a/include/m_name_table.h b/include/m_name_table.h
index f0656d2..4bee1cb 100644
--- a/include/m_name_table.h
+++ b/include/m_name_table.h
@@ -3,6 +3,8 @@
#include "ultra64.h"
+extern u8 npc_looks_table[];
+
#define EMPTY_NO 0x0000
#define ITM_MONEY_START 0x2100
diff --git a/include/m_npc.h b/include/m_npc.h
index 4fb1303..9ce0bad 100644
--- a/include/m_npc.h
+++ b/include/m_npc.h
@@ -5,243 +5,376 @@
#include "m_actor.h"
#include "unk.h"
#include "m_land.h"
-#include "6DB420.h"
+#include "lb_rtc.h"
+#include "libu64/gfxprint.h"
+#include "m_quest.h"
#include "m_mail.h"
+#include "m_private_internals.h"
+#include "overlays/actors/ovl_Npc/ac_npc.h"
+#include "m_field_make.h"
+#include "m_npc_base.h"
-#define ANIMAL_NUM_MAX 15 /* Maximum number of villagers possible in town */
+#define ANIMAL_NUM_MIN 5
+#define ANIMAL_NUM_MAX 15 /* Maximum number of villagers possible in town */
+
+#define ANIMAL_MEMORY_NUM 7
+#define ANIMAL_CATCHPHRASE_LEN 4
+#define ANIMAL_NAME_LEN PLAYER_NAME_LEN
+
+#define NPC_NUM 216
+
+struct Game;
+struct PrivateInfo;
+
+typedef struct NpcHouseData {
+ /* 0x00 */ u8 type;
+ /* 0x01 */ u8 palette;
+ /* 0x02 */ u8 wallId;
+ /* 0x03 */ u8 floorId;
+ /* 0x04 */ u16 mainLayerId;
+ /* 0x06 */ u16 secondaryLayerId;
+} NpcHouseData; // size = 0x8
+
+typedef struct NpcListFlags {
+ /* 0x00 */ u8 beeSting:1; // [8]
+ /* 0x00 */ u8 fishComplete:1; // [7]
+ /* 0x00 */ u8 insectComplete:1; // [6]
+ /* 0x00 */ u8 unk3:6; // [5:0]
+} NpcListFlags; //size = 0x1
typedef struct NpcList {
- /* 0x00 */ char unk00[0x10];
+ /* 0x00 */ u16 name;
+ /* 0x02 */ u16 fieldName;
+ /* 0x04 */ xyz_t homePosition;
/* 0x10 */ xyz_t position;
- /* 0x14 */ char unk14[0x1C];
+ /* 0x1C */ u8 appearFlag;
+ /* 0x1D */ NpcListFlags flags;
+ /* 0x1F */ u8 unk1F;
+ /* 0x20 */ QuestBase questInfo;
+ /* 0x2C */ NpcHouseData houseData;
+ /* 0x34 */ u16 rewardFurniture;
} NpcList; // size = 0x38
-typedef struct AnmHome_c {
+typedef struct Anmland {
+ /* 0x00 */ char name[LAND_NAME_SIZE];
+ /* 0x08 */ u16 id;
+} Anmland; // size = 0x10
+
+typedef struct Anmhome_c {
/* 0x00 */ u8 typeUnused; /* Likely the house type, but seems to be unused outside of SChk_Anmhome_c_sub */
/* 0x01 */ u8 blockX; /* acre x position */
/* 0x02 */ u8 blockZ; /* acre y position */
/* 0x03 */ u8 utX; /* unit x position */
/* 0x04 */ u8 utZ; /* unit z position */
-} AnmHome_c; // size = 0x5
-
-typedef struct AnmPersonalId_c {
- /* 0x00 */ u16 npcId; /* id */
- /* 0x02 */ u16 landId; /* town id */
- /* 0x04 */ u8 landName[LAND_NAME_SIZE]; /* town name */
- /* 0x0A */ u8 nameId; /* lower byte of the id */
- /* 0x0B */ u8 looks; /* internal name for personality */
-} AnmPersonalID_c; // size = 0xC
-
-typedef struct Animal_c {
- /* 0x000 */ AnmPersonalID_c id;
- /* 0x00C */ char unk00C[0x4D4];
- /* 0x4E0 */ AnmHome_c homeInfo;
- /* 0x4E5 */ char unk4E5[0x43];
-} Animal_c;
-
-typedef enum NpcLooks{
- /* 0 */ NPC_LOOKS_GIRL,
- /* 1 */ NPC_LOOKS_KO_GIRL,
- /* 2 */ NPC_LOOKS_BOY,
- /* 3 */ NPC_LOOKS_SPORT_MAN,
- /* 4 */ NPC_LOOKS_GRIM_MAN,
- /* 5 */ NPC_LOOKS_NANIWA_LADY,
-
- /* 6 */ NPC_LOOKS_NUM
-}NpcLooks;
-
-// void func_800A6920_jp();
-// void func_800A6940_jp();
-// void func_800A695C_jp();
-void mNpc_ClearAnimalPersonalID(AnmPersonalID_c*);
-s32 mNpc_CheckFreeAnimalPersonalID(AnmPersonalID_c*);
-void mNpc_CopyAnimalPersonalID(AnmPersonalID_c*, AnmPersonalID_c*);
-s32 mNpc_CheckCmpAnimalPersonalID(AnmPersonalID_c*, AnmPersonalID_c*);
-// void func_800A6AF0_jp();
-// void func_800A6B58_jp();
-// void func_800A6B6C_jp();
-// void func_800A6B7C_jp();
-// void func_800A6B9C_jp();
-// void func_800A6BC8_jp();
-// void func_800A6C1C_jp();
-// void func_800A6C84_jp();
-// void func_800A6CE4_jp();
-// void func_800A6D04_jp();
-// void func_800A6DB0_jp();
-// void func_800A6DD0_jp();
-// void func_800A6E0C_jp();
+} Anmhome_c; // size = 0x5
+
+typedef struct Anmlet {
+ /* 0x00 */ u8 exists:1; /* letter received by villager and exists */
+ /* 0x00 */ u8 cond:1; /* mNpc_LETTER_RANK_* */
+ /* 0x00 */ u8 sendReply:1; /* set when the villager should reply */
+ /* 0x00 */ u8 hasPresentCloth:1; /* set when the villager's held present shirt is from this letter */
+ /* 0x00 */ u8 wearingPresentCloth:1; /* set when a villager is wearing the shirt sent with the saved letter */
+ /* 0x00 */ u8 unk5:3; /* seemingly unused */
+} Anmlet; // size = 0x1
+
+typedef struct AnmRemailFlags {
+ /* 0x00 */ u8 cond:1;
+ /* 0x00 */ u8 looks:7;
+} AnmremailFlags; // size 0x1
+
+typedef struct Anmremail {
+ /* 0x00 */ lbRTC_ymd_t date; /* date sent */
+ /* 0x04 */ char name[ANIMAL_NAME_LEN]; /* villager name */
+ /* 0x0A */ char landName[LAND_NAME_SIZE]; /* town name */
+ /* 0x10 */ AnmremailFlags flags;
+} Anmremail; // size = 0x12
+
+typedef struct Anmplmail_c {
+ /* 0x000 */ u8 font; /* 'font' to use for letter info */
+ /* 0x001 */ u8 paperType;
+ /* 0x002 */ u16 present;
+ /* 0x004 */ u8 headerBackStart; /* position for name insertion in header */
+ /* 0x005 */ u8 header[MAIL_HEADER_LEN];
+ /* 0x00F */ u8 body[MAIL_BODY_LEN];
+ /* 0x06F */ u8 footer[MAIL_FOOTER_LEN];
+ /* 0x07F */ u8 unk7F; /* likely pad */
+ /* 0x080 */ lbRTC_ymd_t date; /* sent date */
+} Anmplmail_c; // size = 0x84
+
+typedef struct AnmGoodbyeMail {
+ /* 0x000 */ AnmPersonalID_c id;
+ /* 0x00C */ u8 deliverTo;
+} AnmGoodbyeMail; // size = 0xE
+
+typedef struct Anmmem_c {
+ /* 0x000 */ PersonalID_c memoryPlayerId; /* personal id of the player memory belongs to */
+ /* 0x014 */ lbRTC_time_c lastSpeakTime; /* time the player last spoke to this villager */
+ /* 0x01C */ Anmland land; /* union between town NPC land memory & islander player action memory */
+ /* 0x028 */ u64 savedTownTune; /* memory origin town tune */
+ /* 0x030 */ s8 friendship; /* friendship with the player */
+ /* 0x031 */ Anmlet letterInfo; /* saved letter flags */
+ /* 0x032 */ Anmplmail_c letter; /* saved letter */
+} Anmmem_c; // size 0xB0
+
+typedef struct Animal_c {
+ /* 0x000 */ AnmPersonalID_c id;
+ /* 0x00C */ Anmmem_c memories[ANIMAL_MEMORY_NUM];
+ /* 0x4E0 */ Anmhome_c homeInfo;
+ /* 0x4E5 */ char catchphrase[ANIMAL_CATCHPHRASE_LEN];
+ /* 0x4E9 */ char unk4E9[0x3];
+ /* 0x4EC */ QuestContest contestQuest;
+ /* 0x4E9 */ char previousLandName[LAND_NAME_SIZE];
+ /* 0x4E9 */ char parentName[ANIMAL_NAME_LEN];
+ /* 0x51C */ u16 previousLandId;
+ /* 0x51E */ u8 mood;
+ /* 0x51F */ u8 moodTime;
+ /* 0x520 */ u16 cloth;
+ /* 0x522 */ u16 removeInfo;
+ /* 0x524 */ u8 isHome;
+ /* 0x525 */ u8 movedIn;
+ /* 0x526 */ u8 isMoving;
+} Animal_c; // size = 0x528
+
+typedef struct SpecialNpcData {
+ /* 0x00 */ u16 specialNpcId;
+ /* 0x02 */ u16 sex;
+ /* 0x04 */ s32 nameStringNumber;
+ /* 0x08 */ s32 soundId;
+} SpecialNpcData; // size = 0xC
+
+typedef struct NpcDefaultData {
+ /* 0x00 */ u16 cloth;
+ /* 0x02 */ u16 catchphraseIdx;
+ /* 0x04 */ s8 umbrella;
+} NpcDefaultData; // size = 0x5
+
+typedef struct NpcTalkInfo {
+ /* 0x00 */ u16 timer;
+ /* 0x02 */ u8 talkNum;
+ /* 0x03 */ u8 questRequest;
+ /* 0x04 */ u16 unlockTimer;
+ /* 0x06 */ u16 resetTimer;
+} NpcTalkInfo; // size = 0x8
+
+typedef struct NpcTemper {
+ /* 0x0 */ u16 unlockTimer;
+ /* 0x2 */ u8 overImpatientNum;
+ /* 0x3 */ u8 talkNumMax;
+} NpcTemper; // size = 0x4
+
+typedef struct NpcEvent {
+ /* 0x0 */ u16 eventId;
+ /* 0x2 */ u16 textureId;
+ /* 0x4 */ u16 npcId;
+ /* 0x6 */ u16 clothId;
+ /* 0x8 */ u8 exists;
+ /* 0x9 */ u8 use;
+ /* 0xA */ u16 unkA;
+} NpcEvent; // size = 0xC
+
+typedef struct DemoNpc {
+ /* 0x00 */ u16 npcName; /* villager id */
+ /* 0x04 */ u32 blockX; // spawn acre x
+ /* 0x08 */ u32 blockZ; // spawn acre z
+ /* 0x0C */ u32 utX; // spawn unit x in acre
+ /* 0x10 */ u32 utZ; // spawn unit z in acre
+} DemoNpc; // size = 0x14
+
+
+void mNpc_MakeRandTable(s32* table, s32 count, s32 swapNum);
+void mNpc_ClearBufSpace1(u8* buf, s32 size);
+void mNpc_AddNowNpcMax(u8* npcMax);
+void mNpc_SubNowNpcMax(u8* npcMax);
+void mNpc_ClearAnimalPersonalID(AnmPersonalID_c* pid);
+s32 mNpc_CheckFreeAnimalPersonalID(AnmPersonalID_c* pid);
+void mNpc_CopyAnimalPersonalID(AnmPersonalID_c* dst, AnmPersonalID_c* src);
+s32 mNpc_CheckCmpAnimalPersonalID(AnmPersonalID_c* id0, AnmPersonalID_c* id1);
+s32 mNpc_GetAnimalNum(void);
+s32 mNpc_CheckRemoveExp(Animal_c* animal);
+s32 mNpc_GetRemoveTime(Animal_c* animal);
+void mNpc_AddRemoveTime(Animal_c* animal);
+void mNpc_SetRemoveExp(Animal_c* animal, u16 removeExp);
+void mNpc_SetParentName(Animal_c* animal, PersonalID_c* parentId);
+void mNpc_SetParentNameAllAnimal(void);
+void mNpc_ClearAnimalMail(Anmplmail_c* mail);
+void mNpc_CopyAnimalMail(Anmplmail_c* dst, Anmplmail_c* src);
+void mNpc_ClearAnimalMemory(Anmmem_c* memory, s32 num);
+void mNpc_CopyAnimalMemory(Anmmem_c* dst, Anmmem_c* src);
+void mNpc_AddFriendship(Anmmem_c* memory, s32 amount);
+s32 mNpc_CheckFreeAnimalMemory(Anmmem_c* memory);
void mNpc_RenewalAnimalMemory(void);
-// void func_800A6F48_jp();
-// void func_800A6FF4_jp();
-// void func_800A706C_jp();
-// void func_800A71AC_jp();
-// void func_800A71F8_jp();
-// void func_800A7238_jp();
-// void func_800A72C0_jp();
-// void func_800A73D8_jp();
-// void func_800A74A0_jp();
-// void func_800A7530_jp();
-// void func_800A75FC_jp();
-// void func_800A76E4_jp();
-// void func_800A77F0_jp();
-// void func_800A7858_jp();
-// void func_800A78DC_jp();
-// void mNpc_ClearAnimalInfo();
-// void mNpc_ClearAnyAnimalInfo();
-s32 mNpc_CheckFreeAnimalInfo(Animal_c*);
-// void mNpc_GetFreeAnimalInfo();
-// void mNpc_UseFreeAnimalInfo();
-// void mNpc_CopyAnimalInfo();
-// void mNpc_SearchAnimalinfo();
-// void func_800A7C94_jp();
-// void func_800A7D08_jp();
-// void func_800A7DA0_jp();
-// void mNpc_GetOtherAnimalPersonalID();
-// void func_800A80D8_jp();
-// void func_800A8148_jp();
-// void func_800A820C_jp();
-// void func_800A82C8_jp();
-// void func_800A8344_jp();
-// void func_800A83F0_jp();
-// void func_800A845C_jp();
-// void func_800A8614_jp();
-// void func_800A86C4_jp();
-// void func_800A86E8_jp();
-// void func_800A8764_jp();
-// void func_800A8814_jp();
-// void func_800A8868_jp();
-// void func_800A8AB4_jp();
-// void func_800A8B10_jp();
-// void func_800A8B84_jp();
-// void func_800A8C48_jp();
-// void func_800A8DB4_jp();
-// void func_800A8F30_jp();
-// void func_800A9028_jp();
-// void func_800A9110_jp();
-// void func_800A918C_jp();
-void func_800A91DC_jp(void);
-// void func_800A9364_jp();
-// void func_800A93AC_jp();
-// void func_800A9468_jp();
-// void func_800A94C8_jp();
-// void func_800A956C_jp();
-// void func_800A96B0_jp();
-// void func_800A9780_jp();
-// void func_800A992C_jp();
-// void func_800A99B8_jp();
-// void func_800A9A98_jp();
-// void func_800A9BC4_jp();
-// void func_800A9BD4_jp();
-// void func_800A9CD4_jp();
-// void func_800A9D68_jp();
-// void func_800A9E54_jp();
-// void func_800A9E7C_jp();
-// void func_800A9EC8_jp();
-// void func_800A9F9C_jp();
-// void func_800AA028_jp();
-// void func_800AA0B8_jp();
-void func_800AA124_jp(void);
-// void func_800AA14C_jp();
-s32 mNpc_GetLooks(u16 arg0);
-// void func_800AA218_jp();
-// void func_800AA29C_jp();
-// void func_800AA2F8_jp();
-// void func_800AA35C_jp();
-// void func_800AA3A4_jp();
-// void func_800AA438_jp();
-// void func_800AA49C_jp();
-// void func_800AA4FC_jp();
-// void func_800AA51C_jp();
-// void mNpc_SetAnimalTitleDemo();
-// void func_800AA8C4_jp();
-// void func_800AA9F4_jp();
-// void func_800AAA40_jp();
-// void func_800AAB48_jp();
-// void func_800AAC88_jp();
-// void func_800AADE8_jp();
-// void func_800AAEFC_jp();
-void func_800AB054_jp(void);
-void func_800AB09C_jp(void);
-void mNpc_SetNpcList(NpcList* npclist, Animal_c* animals, s32 count, s32 malloc_flag);
-void mNpc_SetNpcinfo(struct Actor* actor, s8 arg1);
-// void func_800AB498_jp();
-// void func_800AB62C_jp();
-// void func_800AB6C8_jp();
-// void func_800AB734_jp();
-// void func_800AB7D0_jp();
-// void func_800AB80C_jp();
-// void func_800AB8A0_jp();
-// void func_800ABA14_jp();
-// void func_800ABAA8_jp();
-// void func_800ABAF0_jp();
-s32 mNpc_GetInAnimalP(void);
-// void func_800ABB24_jp();
-// void func_800ABCF8_jp();
+s32 mNpc_GetOldAnimalMemoryIdx(Anmmem_c* memory, s32 num);
+s32 mNpc_GetFreeAnimalMemoryIdx(Anmmem_c* memory, s32 num);
+s32 mNpc_ForceGetFreeAnimalMemoryIdx(Anmmem_c* memory, s32 num);
+void mNpc_SetAnimalMemory_NotSetDay(PersonalID_c* pid, Anmmem_c* memory);
+void mNpc_SetAnimalMemory(PersonalID_c* pid, Anmmem_c* memory);
+s32 mNpc_GetAnimalMemoryIdx(PersonalID_c* pid, Anmmem_c* memory, s32 num);
+void mNpc_SetAnimalLastTalk(Animal_c* animal);
+void mNpc_SetAnimalPersonalID2Memory(AnmPersonalID_c* anmId);
+s32 mNpc_GetHighestFriendshipIdx(Anmmem_c* memory, s32 num);
+s32 mNpc_SelectBestFriend(Anmmem_c** bestFriendMem, Anmmem_c* memory, s8* bestFriendFriendShip);
+s32 mNpc_GetAnimalMemoryBestFriend(Anmmem_c* memory, s32 num);
+s32 mNpc_GetAnimalMemoryFriend_Land_Sex(Anmmem_c* memory, s32 num, s32 sex);
+s32 mNpc_GetAnimalMemoryNum(Anmmem_c* memory, s32 count);
+s32 mNpc_GetAnimalMemoryLetterNum(Anmmem_c* memory, s32 count);
+s32 mNpc_GetAnimalMemoryLandKindNum(Anmmem_c* memory, s32 count);
+void mNpc_ClearAnimalInfo(Animal_c* animal);
+void mNpc_ClearAnyAnimalInfo(Animal_c* animals, s32 count);
+s32 mNpc_CheckFreeAnimalInfo(Animal_c* animal);
+s32 mNpc_GetFreeAnimalInfo(Animal_c* animal, s32 count);
+s32 mNpc_UseFreeAnimalInfo(Animal_c* animal, s32 count);
+void mNpc_CopyAnimalInfo(Animal_c* dst, Animal_c* src);
+s32 mNpc_SearchAnimalinfo(Animal_c* animal, u16 npcName, s32 count);
+Animal_c* mNpc_GetAnimalInfoP(u16 id);
+s32 mNpc_SearchAnimalPersonalID(AnmPersonalID_c* id);
+AnmPersonalID_c* mNpc_GetOtherAnimalPersonalIDOtherBlock(AnmPersonalID_c* pids, s32 count, s32 blockX, s32 blockY, s32 flag);
+AnmPersonalID_c* mNpc_GetOtherAnimalPersonalID(AnmPersonalID_c* pids, s32 count);
+void mNpc_SetAnimalThisLand(Animal_c* animal, s32 count);
+s32 mNpc_GetSameLooksNum(u8 looks);
+s32 mNpc_CheckNpcExistBlock(s32 idx, s32 checkBx, s32 checkBz);
+void mNpc_Mail2AnimalMail(Anmplmail_c* animalMail, Mail_c* mail);
+void mNpc_AnimalMail2Mail(Mail_c* mail, Anmplmail_c* animal_mail, PersonalID_c* pid, AnmPersonalID_c* anmId);
+s32 mNpc_CheckMailChar(u8 c);
+s32 mNpc_CheckNormalMail_sub(s32* num, u8* body);
+u8 mNpc_CheckNormalMail_length(s32* len, u8* body);
+u8 mNpc_CheckNormalMail(u8* body);
+s32 mNpc_SetMailCondThisLand(Anmmem_c* memory, u8* body);
+s32 mNpc_SetMailCondOtherLand(Animal_c* animal, u8* body);
+s32 mNpc_SetRemailCond(Animal_c* animal, Anmmem_c* memory, u8* body);
+s32 mNpc_SendMailtoNpc(Mail_c* mail);
+void mNpc_ClearRemail(Anmremail* remail);
+void mNpc_GetRemailPresent(u16* present);
+s32 mNpc_GetHandbillz(Mail_c* mail, s32 superNum, s32 mailANum, s32 mailBNum, s32 mailCNum, s32 psNum);
+void mNpc_SetRemailFreeString(PersonalID_c* pid, AnmPersonalID_c* anmId, Anmremail* remail);
+void mNpc_GetRemailGoodData(Mail_c* mail, PersonalID_c* pid, AnmPersonalID_c* anmId, Anmremail* remail, u8 foreign);
+void mNpc_GetRemailWrongData(Mail_c* mail, PersonalID_c* pid, AnmPersonalID_c* anmId, Anmremail* remail, u8 foreign);
+void mNpc_GetRemailData(Mail_c* mail, PersonalID_c* pid, AnmPersonalID_c* anmId, Anmremail* remail, s32 cond, u8 foreign);
+s32 mNpc_SendRemailPostOffice(PersonalID_c* pid, AnmPersonalID_c* anmId, Anmremail* remail, s32 cond, u8 foreign);
+s32 mNpc_CheckLetterTime(lbRTC_ymd_t* letterDate, lbRTC_time_c* rtcTime);
+void mNpc_Remail(void);
+u8 mNpc_GetPaperType(void);
+void mNpc_LoadMailDataCommon2(Mail_c* mail, PersonalID_c* pid, AnmPersonalID_c* amnId, u16 present, u8 paperType, s32 mailNo);
+void mNpc_GetEventPresent(u16* present, s32 type);
+void mNpc_GetEventMail(Mail_c* mail, PersonalID_c* pid, AnmPersonalID_c* anmId, s32 type, s32 looks);
+s32 mNpc_SendEventPresentMail(PersonalID_c* pid, s32 playerNo, AnmPersonalID_c* anmId, s32 type);
+void mNpc_SendEventPresentMailSex(s32* selected, u8* type, Animal_c* animal, NpcSex sex);
+s32 mNpc_SendEventPresentMail_common(NpcSex sexType);
+void mNpc_GetBirthdayPresent(u16* present);
+void mNpc_GetBirthdayCard(Mail_c* mail, PersonalID_c* pid, AnmPersonalID_c* anmId);
+s32 mNpc_SendBirthdayCard(PersonalID_c* pid, s32 playerNo, AnmPersonalID_c* anm_id);
+s32 mNpc_SendEventBirthdayCard(PersonalID_c* pid);
+s32 mNpc_SendEventBirthdayCard2(PersonalID_c* pid, s32 playerNo);
+void mNpc_GetXmasCardData(Mail_c* mail, PersonalID_c* pid);
+s32 mNpc_SendEventXmasCard(PersonalID_c* pid, s32 playerNo);
+void mNpc_SetWordEnding(Animal_c* animal, char* catchphrase);
+char* mNpc_GetWordEnding(Actor* actor);
+void mNpc_ResetWordEnding(Actor* actor);
+s32 mNpc_GetFreeEventNpcIdx(void);
+s32 mNpc_RegistEventNpc(u16 eventId, u16 textureId, u16 npcId, u16 clothId);
+void mNpc_UnRegistEventNpc(u16 eventId);
+void mNpc_ClearEventNpc(void);
+NpcEvent* mNpc_GetSameEventNpc(u16 eventId);
+u8 mNpc_GetLooks(u16 npcId);
+void mNpc_SetDefAnimalInfo(Animal_c* animal, u16 npcId, u8 looks, NpcDefaultData* defaultData);
+void mNpc_SetDefAnimal(Animal_c* animal, u16 npcId, NpcDefaultData* defaultData);
+void mNpc_SetHaveAppeared(u16 npcId);
+s32 mNpc_GetHaveAppeared_idx(s32 idx);
+s32 mNpc_GetLooks2NotHaveAppearedNum(u8 id);
+void mNpc_ResetHaveAppeared_common(u8* npcUsedTable, Animal_c* animal);
+void mNpc_ResetHaveAppeared(void);
+s32 mNpc_GetDefGrowPermission(s32 idx, s8* growList, s32 count);
+void mNpc_DecideLivingNpcMax(Animal_c* animal, u8 count, s32 mallocFlag);
+void mNpc_SetAnimalTitleDemo(DemoNpc* demo, Animal_c* animal, struct Game* game);
+s32 mNpc_GetReservedUtNum(s32* utX, s32* utZ, u16* item);
+s32 mNpc_BlockNum2ReservedUtNum(s32* utX, s32* utZ, s32 bx, s32 bz);
+void mNpc_MakeReservedListBeforeFieldct(Anmhome_c* reserved, s32 reservedNum, u8* reservedCount);
+void mNpc_MakeReservedListAfterFieldct(Anmhome_c* reserved, s32 reservedNum, u8* reserved_count, u8 bxMax, u8 bzMax);
+void mNpc_BuildHouseBeforeFieldct(u16 npcId, s32 bx, s32 bz, s32 utX, s32 utZ);
+void mNpc_DestroyHouse(Anmhome_c* home);
+void mNpc_SetNpcHome(Animal_c* animal, Anmhome_c* reserved, u8 reserved_num);
+void mNpc_InitNpcData(void);
+void mNpc_InitNpcList(void);
+void mNpc_SetNpcList(NpcList* npclist, Animal_c* animal, s32 count, s32 mallocFlag);
+void mNpc_SetNpcinfo(Actor* actor, s8 npcInfoIdx);
+void mNpc_AddNpc_inNpcRoom(FieldMakeMoveActor* moveActor, u8 bx, u8 bz);
+void mNpc_RenewalNpcRoom(s16* wallFloor);
+void mNpc_RenewalSetNpc(Actor* actor);
+s32 mNpc_GetFriendAnimalNum(PersonalID_c* pid);
+s32 mNpc_CheckFriendAllAnimal(PersonalID_c* pid);
+s32 mNpc_CheckSelectFurniture(u16 item);
+u16 func_800AB8A0_jp(FieldMakeFGData**, NpcList*, s32);
+void mNpc_SetNpcFurnitureRandom(FieldMakeFGData** data, s32 base);
+u16 mNpc_GetNpcFurniture(AnmPersonalID_c* anmId);
+void mNpc_ClearInAnimal(void);
+Animal_c* mNpc_GetInAnimalP(void);
+u8 mNpc_DecideRemoveAnimalNo(Animal_c* animal, s32 max);
+
void mNpc_SetRemoveAnimalNo(Animal_c* animal);
-// void func_800ABE30_jp();
-// void func_800ABF40_jp();
-// void func_800AC1A0_jp();
-// void func_800AC1C8_jp();
-// void func_800AC1EC_jp();
-// void func_800AC284_jp();
-// void func_800AC358_jp();
-// void func_800AC488_jp();
+s32 mNpc_CheckGoodbyAnimalMemoryNum(Animal_c* a0, Animal_c* a1);
+s32 mNpc_GetGoodbyAnimalIdx(void);
+void mNpc_ClearGoodbyMail(AnmGoodbyeMail* mail);
+void mNpc_FirstClearGoodbyMail(void);
+void mNpc_SetGoodbyAnimalMail(AnmGoodbyeMail* mail, Animal_c* animal);
+s32 mNpc_SetGoodbyMailData(Mail_c* mail, PersonalID_c* pid, AnmPersonalID_c* anm_id);
+s32 mNpc_SendGoodbyAnimalMailOne(Mail_c* mail, struct PrivateInfo* priv, s32 playerNo, AnmPersonalID_c* anmId);
+void mNpc_SendGoodbyAnimalMail(AnmGoodbyeMail* mail);
void mNpc_SendRegisteredGoodbyMail(void);
-// void func_800AC57C_jp();
-// void func_800AC804_jp();
-void mNpc_SetReturnAnimal(s32 arg0);
-// void func_800ACB24_jp();
-// void func_800ACB54_jp();
-// void func_800ACC38_jp();
-// void func_800ACCAC_jp();
-void mNpc_GetNpcWorldNameAnm(PlayerName* arg0, struct mMl_get_npcinfo_from_mail_name_arg0* arg1);
-// void func_800ACD74_jp();
-// void func_800ACDF8_jp();
-// void func_800ACE90_jp();
-void mNpc_GetAnimalPlateName(char* arg0, xyz_t arg1);
-// void func_800AD084_jp();
-// void func_800AD0B8_jp();
-// void func_800AD104_jp();
-// void func_800AD154_jp();
-// void func_800AD188_jp();
-// void func_800AD1E0_jp();
-// void func_800AD22C_jp();
-// void func_800AD2B8_jp();
-void mNpc_InitNpcAllInfo(s32 arg0);
-// void func_800AD338_jp();
-// void func_800AD3BC_jp();
-// void func_800AD4B8_jp();
-// void func_800AD614_jp();
-// void func_800AD6D4_jp();
-// void func_800AD8C4_jp();
-// void func_800AD954_jp();
-void func_800AD9FC_jp(void);
-// void func_800ADBE4_jp();
-// void func_800ADC28_jp();
-// void func_800ADC8C_jp();
-// void func_800ADD20_jp();
-// void func_800ADEFC_jp();
-// void func_800AE110_jp();
+void mNpc_GetRemoveAnimal(Animal_c* transferAnimal, s32 movingOut);
+s32 mNpc_CheckBuildHouse(s32 blockX, s32 blockZ, u8 utX, u8 utZ);
+void mNpc_SetReturnAnimal(Animal_c* returnAnimal);
+void mNpc_AddActor_inBlock(FieldMakeMoveActor* moveActor, u8 bx, u8 bz);
+void mNpc_SetNpcNameID(Animal_c* animal, s32 count);
+void mNpc_LoadNpcNameString(char* name, u8 npcId);
+void mNpc_GetNpcWorldNameTableNo(char* name, u16 npcId);
+void mNpc_GetNpcWorldNameAnm(char* name, AnmPersonalID_c* anmId);
+void mNpc_GetNpcWorldNameP(char* name, u16 npcId);
+void mNpc_GetNpcWorldName(char* name,Npc* npc);
+void mNpc_GetRandomAnimalName(char* dst);
+void mNpc_GetAnimalPlateName(char* dst, xyz_t wpos);
+NpcLooks mNpc_GetNpcLooks(Actor* actor);
+NpcSex mNpc_GetActorSex(u16 npcId);
+NpcSex mNpc_GetLooks2Sex(NpcLooks looks);
+NpcSex mNpc_GetAnimalSex(Animal_c* animal);
+NpcSex mNpc_GetNpcSex(Actor* actor);
+s32 mNpc_GetNpcSoundSpecNotAnimal(u16 npcId);
+s32 mNpc_GetNpcSoundSpec(Actor* actor);
+void mNpc_GetMsg(s32 arg);
+void mNpc_InitNpcAllInfo(s32 mallocFlag);
+s32 mNpc_CheckGrowFieldRank(void);
+s32 mNpc_CheckGrow(void);
+u8 mNpc_GetMinLooks(u8* bitfield, s32* minLooksNum);
+NpcSex mNpc_GetMinSex(void);
+s32 mNpc_GrowLooksNpcIdx(u8 looks);
+void mNpc_SetAnimalInfoNpcIdx(Animal_c* animal, s32 idx);
+s32 mNpc_SetGrowNpc(u8 looks);
+void mNpc_Grow(void);
+s32 mNpc_CheckNpcSet_fgcol(u16 arg0, u32 arg1);
+s32 mNpc_CheckNpcSet_fgcol_hard(u16 arg0, u32 arg1);
+s32 mNpc_CheckNpcSet(s32 bx, s32 bz, s32 ut_x, s32 ut_z);
+s32 mNpc_GetMakeUtNuminBlock_hard_area(s32* utX, s32* utZ, s32 bx, s32 bz, s32 restrictArea);
+s32 mNpc_GetMakeUtNuminBlock_area(s32* utX, s32* utZ, s32 bx, s32 bz, s32 restrictArea);
+s32 mNpc_GetMakeUtNuminBlock(s32* utX, s32* utZ, s32 bx, s32 bz);
void mNpc_ClearTalkInfo(void);
-// void func_800AE1A0_jp();
-// void func_800AE1B8_jp();
-// void func_800AE1D8_jp();
-// void func_800AE23C_jp();
-// void func_800AE284_jp();
-// void func_800AE2E8_jp();
-// void func_800AE320_jp();
-// void func_800AE37C_jp();
-// void func_800AE3B4_jp();
-// void func_800AE4B4_jp();
-// void func_800AE558_jp();
-// void func_800AE5C8_jp();
-// void func_800AE64C_jp();
-// void func_800AE670_jp();
-// void func_800AE694_jp();
-// void func_800AE6B0_jp();
-// void func_800AE6CC_jp();
-// void func_800AE76C_jp();
-// void func_800AE898_jp();
-// void mNpc_PrintFriendship_fdebug();
+void mNpc_TimerCountDown(NpcTalkInfo* talkInfo);
+void mNpc_SetUnlockTimer(u16* unlockTimer, u16* resetTimer, s32 feel);
+s32 mNpc_CountTalkNum(s32 animalIdx, s32 feel);
+s32 mNpc_CheckOverImpatient(s32 animalIdx, s32 feel);
+s32 mNpc_GetOverImpatient(s32 animalIdx, s32 feel);
+s32 mNpc_CheckQuestRequest(s32 animalIdx);
+void mNpc_SetQuestRequestOFF(s32 animalIdx, s32 feel);
+void mNpc_UnlockTimerCountDown(NpcTalkInfo* talkInfo);
+void mNpc_TalkInfoMove(void);
+void mNpc_TalkEndMove(s32 animalIdx, s32 feel);
+s32 mNpc_GetNpcFloorNo(void);
+void mNpc_SetTalkBee(void);
+u8 mNpc_GetFishCompleteTalk(NpcList* npclist);
+u8 mNpc_GetInsectCompleteTalk(NpcList* npclist);
+void mNpc_SetFishCompleteTalk(NpcList* npclist);
+void mNpc_SetInsectCompleteTalk(NpcList* npclist);
+void mNpc_SetNpcHomeYpos(void);
+void mNpc_PrintRemoveInfo(gfxprint* gfxprint);
+void mNpc_SetTalkAnimalIdx_fdebug(AnmPersonalID_c* anm_id);
+void mNpc_PrintFriendship_fdebug(gfxprint* gfxprint);
+
#endif
diff --git a/include/m_npc_base.h b/include/m_npc_base.h
new file mode 100644
index 0000000..c98d121
--- /dev/null
+++ b/include/m_npc_base.h
@@ -0,0 +1,48 @@
+#ifndef M_NPC_BASE_H
+#define M_NPC_BASE_H
+
+#include "ultra64.h"
+
+typedef struct AnmPersonalId_c {
+ /* 0x00 */ u16 npcId; /* id */
+ /* 0x02 */ u16 landId; /* town id */
+ /* 0x04 */ char landName[LAND_NAME_SIZE]; /* town name */
+ /* 0x0A */ u8 nameId; /* lower byte of the id */
+ /* 0x0B */ u8 looks; /* internal name for personality */
+} AnmPersonalID_c; // size = 0xC
+
+typedef enum NpcSex {
+ /* 0 */ NPC_SEX_MALE,
+ /* 1 */ NPC_SEX_FEMALE,
+ /* 2 */ NPC_SEX_OTHER
+} NpcSex;
+
+typedef enum NpcLooks {
+ /* 0 */ NPC_LOOKS_GIRL,
+ /* 1 */ NPC_LOOKS_KO_GIRL,
+ /* 2 */ NPC_LOOKS_BOY,
+ /* 3 */ NPC_LOOKS_SPORT_MAN,
+ /* 4 */ NPC_LOOKS_GRIM_MAN,
+ /* 5 */ NPC_LOOKS_NANIWA_LADY,
+ /* 6 */ NPC_LOOKS_NUM
+} NpcLooks;
+
+typedef enum NpcFeels {
+ /* 0 */ NPC_FEEL_NORMAL,
+ /* 1 */ NPC_FEEL_HAPPY,
+ /* 2 */ NPC_FEEL_ANGRY,
+ /* 3 */ NPC_FEEL_SAD,
+ /* 4 */ NPC_FEEL_SLEEPY,
+ /* 5 */ NPC_FEEL_PITFALL,
+ /* 6 */ NPC_FEEL_NUM
+} NpcFeels;
+
+typedef enum NpcPatience {
+ /* 0 */ NPC_PATIENCE_MILDLY_ANNOYED,
+ /* 1 */ NPC_PATIENCE_ANNOYED,
+ /* 2 */ NPC_PATIENCE_NORMAL,
+ /* 3 */ NPC_PATIENCE_NUM
+} NpcPatience;
+
+#endif
+
diff --git a/include/m_private.h b/include/m_private.h
index caf8a80..f966bde 100644
--- a/include/m_private.h
+++ b/include/m_private.h
@@ -4,6 +4,8 @@
#include "ultra64.h"
#include "m_mail.h"
#include "m_quest.h"
+#include "m_private_internals.h"
+#include "m_npc.h"
#include "unk.h"
#define mPr_FOREIGN_MAP_COUNT 8
@@ -24,49 +26,113 @@ typedef enum mPr_ITEM_COND{
/* 3 */ mPr_ITEM_COND_NUM
} mPr_ITEM_COND;
-#define mPr_POCKETS_SLOT_COUNT 15
-#define mPr_DELIVERY_QUEST_NUM mPr_POCKETS_SLOT_COUNT
-#define mPr_ERRAND_QUEST_NUM 5
-
-typedef struct Private_Sub_A86 {
- /* 0x00 */ char unk00[0x3];
- /* 0x03 */ u8 unk_03;
- /* 0x04 */ char unk04[0x1];
- /* 0x05 */ u8 unk_05;
- /* 0x06 */ u16 unk_06;
- /* 0x08 */ u8 unk_08;
-} Private_Sub_A86; // size >= 0xA
-
-typedef struct mPr_map_info_c {
- /* 0x00 */ char unk00[0x8];
-} mPr_map_info_c; // size = 0x8
-
-typedef struct PrivateInventory {
- /* 0x00 */ u16 pockets[mPr_POCKETS_SLOT_COUNT]; /* items in inventory */
- /* 0x1E */ u8 lotto_ticket_expiry_month;
- /* 0x1F */ u8 lotto_ticket_mail_storage;
- /* 0x20 */ u32 item_conditions; /* bitfield (15 values), 2 bits per pocket slot */
- /* 0x24 */ u32 wallet;
- /* 0x28 */ u32 loan;
-} PrivateInventory; // size = 0x2C
-
typedef struct PrivateInfo {
- /* 0x000 */ UNK_TYPE1 unk000[0x10];
+ /* 0x000 */ PersonalID_c playerId;
/* 0x010 */ s8 gender;
/* 0x011 */ UNK_TYPE1 unk011[0x3];
/* 0x014 */ PrivateInventory inventory;
/* 0x040 */ mQst_delivery_c deliveries[mPr_DELIVERY_QUEST_NUM]; /* delivery quests */
- /* 0x25C */ mQst_errand_c errands[mPr_ERRAND_QUEST_NUM]; /* errand quests */
+ /* 0x25C */ QuestErrand errands[mPr_ERRAND_QUEST_NUM]; /* errand quests */
/* 0x3EC */ UNK_TYPE1 unk_3EC[0x2];
/* 0x3EE */ MailHeaderCommon unk_3EE;
- /* 0x40A */ Mail unk_40A[10];
+ /* 0x40A */ Mail_c unk_40A[10];
/* 0xA72 */ UNK_TYPE1 unk_A72[0x2];
/* 0xA74 */ u8 exists;
/* 0xA75 */ UNK_TYPE1 unkA75[0x11];
/* 0xA86 */ Private_Sub_A86 unk_A86;
- /* 0xA90 */ UNK_TYPE1 unkA8F[0xF8];
+ /* 0xA8F */ UNK_TYPE1 unkA8F[0x3c];
+ /* 0xACB */ Anmremail remail;
+ /* 0xADE */ char unkADE[06];
+ /* 0xADE */ PrivateAnimalMemory animalMemory;
+ /* 0xAE4 */ UNK_TYPE1 unkAEA[0x9C];
/* 0xB88 */ mPr_map_info_c maps[mPr_FOREIGN_MAP_COUNT]; /* maps 'collected' for foreign towns */
/* 0xBC8 */ UNK_TYPE1 unkBC8[0x8];
} PrivateInfo; // size = 0xBD0
+void mPr_ClearPlayerName(char* arg0);
+void mPr_CopyPlayerName(char* dst, char* src);
+s32 mPr_NullCheckPlayerName(char* arg0);
+// void func_800B7804_jp();
+// void func_800B785C_jp();
+s32 mPr_NullCheckPersonalID(PersonalID_c* arg0);
+void mPr_ClearPersonalID(PersonalID_c* arg0);
+// void func_800B7998_jp();
+void mPr_CopyPersonalID(PersonalID_c* arg0, PersonalID_c* arg1);
+s32 mPr_CheckCmpPersonalID(PersonalID_c* arg0, PersonalID_c* arg1);
+// void func_800B7A94_jp();
+// void func_800B7AB0_jp();
+void mPr_ClearPrivateInfo(PrivateInfo* private);
+// void func_800B7B8C_jp();
+// void func_800B7BC0_jp();
+// void func_800B7CD0_jp();
+// void func_800B7D50_jp();
+void mPr_InitPrivateInfo(PrivateInfo* private);
+// void func_800B7F00_jp();
+// void func_800B7F48_jp();
+s32 mPr_CheckPrivate(PrivateInfo* private);
+// void func_800B7FA0_jp();
+s32 mPr_GetPrivateIdx(PersonalID_c* arg0);
+// void func_800B8068_jp();
+// void func_800B80B4_jp();
+// void func_800B8128_jp();
+// void func_800B81A4_jp();
+// void func_800B8204_jp();
+// void func_800B828C_jp();
+// void func_800B8318_jp();
+// void func_800B83D4_jp();
+// void func_800B8544_jp();
+// void func_800B86EC_jp();
+// void func_800B88EC_jp();
+// void func_800B8A88_jp();
+void mPr_SetPossessionItem(PrivateInfo* priv, int idx, u16 item, u32 cond);
+// void func_800B8B8C_jp();
+// void func_800B8BE4_jp();
+// void func_800B8C10_jp();
+// void func_800B8C20_jp();
+// void func_800B8C34_jp();
+// void func_800B8C9C_jp();
+// void func_800B8D18_jp();
+// void func_800B8D3C_jp();
+s32 func_800B8D64_jp(u8 player_no, s32 arg1);
+void mPr_ClearMotherMailInfo(PrivateMotherMail* arg0);
+// void func_800B8F20_jp();
+// void func_800B8FB8_jp();
+// void func_800B9038_jp();
+// void func_800B9170_jp();
+// void func_800B9350_jp();
+// void func_800B93AC_jp();
+// void func_800B947C_jp();
+// void func_800B94E0_jp();
+// void func_800B9704_jp();
+// void func_800B9790_jp();
+// void func_800B97C8_jp();
+// void func_800B97F8_jp();
+// void func_800B996C_jp();
+// void func_800B9AF0_jp();
+void func_800B9B2C_jp(void);
+// void func_800B9C34_jp();
+void mPr_SendForeingerAnimalMail(PrivateInfo* privateInfo);
+void mPr_StartSetCompleteTalkInfo(void);
+// void func_800B9E90_jp();
+// void func_800B9EB4_jp();
+// void func_800B9ED4_jp();
+// void func_800B9F00_jp();
+// void func_800B9F74_jp();
+// void func_800B9FA0_jp();
+// void func_800BA014_jp();
+// void func_800BA054_jp();
+// void func_800BA09C_jp();
+// void func_800BA0E4_jp();
+// void func_800BA130_jp();
+// void func_800BA150_jp();
+// void func_800BA18C_jp();
+// void func_800BA214_jp();
+// void func_800BA2B0_jp();
+// void func_800BA2D4_jp();
+// void func_800BA344_jp();
+// void func_800BA3D0_jp();
+void mPr_RenewalMapInfo(mPr_map_info_c* maps, s32 count, struct LandInfo* landInfo);
+// void mPr_RandomSetPlayerData_title_demo();
+// void mPr_PrintMapInfo_debug();
+
#endif
diff --git a/include/m_private_internals.h b/include/m_private_internals.h
new file mode 100644
index 0000000..84c6b3c
--- /dev/null
+++ b/include/m_private_internals.h
@@ -0,0 +1,51 @@
+#ifndef M_PRIVATE_INTERNALS_H
+#define M_PRIVATE_INTERNALS_H
+
+#include "ultra64.h"
+#include "m_land.h"
+
+#define mPr_POCKETS_SLOT_COUNT 15
+#define mPr_DELIVERY_QUEST_NUM mPr_POCKETS_SLOT_COUNT
+#define mPr_ERRAND_QUEST_NUM 5
+
+#define PLAYER_NAME_LEN 6
+
+typedef struct PersonalID_c {
+ /* 0x00 */ char playerName[PLAYER_NAME_LEN];
+ /* 0x06 */ char landName[LAND_NAME_SIZE];
+ /* 0x0C */ u16 playerId;
+ /* 0x0E */ u16 landId;
+} PersonalID_c; // size = 0x10
+
+typedef struct Private_Sub_A86 {
+ /* 0x00 */ char unk00[0x3];
+ /* 0x03 */ u8 unk_03;
+ /* 0x04 */ char unk04[0x1];
+ /* 0x05 */ u8 unk_05;
+ /* 0x06 */ u16 unk_06;
+ /* 0x08 */ u8 unk_08;
+} Private_Sub_A86; // size >= 0xA
+
+typedef struct mPr_map_info_c {
+ /* 0x00 */ char unk00[0x8];
+} mPr_map_info_c; // size = 0x8
+
+typedef struct PrivateMotherMail {
+ /* 0x00 */ UNK_TYPE1 unk_00[0xE];
+} PrivateMotherMail; // size = 0xE
+
+typedef struct PrivateAnimalMemory{
+ /* 0x00 */ u16 npcId;
+ /* 0x02 */ char landName[LAND_NAME_SIZE];
+}PrivateAnimalMemory; // size 0x8
+
+typedef struct PrivateInventory {
+ /* 0x00 */ u16 pockets[mPr_POCKETS_SLOT_COUNT]; /* items in inventory */
+ /* 0x1E */ u8 lotto_ticket_expiry_month;
+ /* 0x1F */ u8 lotto_ticket_mail_storage;
+ /* 0x20 */ u32 item_conditions; /* bitfield (15 values), 2 bits per pocket slot */
+ /* 0x24 */ u32 wallet;
+ /* 0x28 */ u32 loan;
+} PrivateInventory; // size = 0x2C
+
+#endif
diff --git a/include/m_quest.h b/include/m_quest.h
index 671d511..84732b2 100644
--- a/include/m_quest.h
+++ b/include/m_quest.h
@@ -2,19 +2,123 @@
#define M_QUEST_H
#include "ultra64.h"
+#include "lb_rtc.h"
+#include "m_private_internals.h"
+#include "m_npc_base.h"
+
+typedef struct QuestBase {
+ /* 0x00 */ u32 questType:2; /* type, 0 = delivery, 1 = errand, 2 = contest, 3 = none */
+ /* 0x00 */ u32 questKind:6; /* kind, differs by type */
+ /* 0x01 */ u32 timeLimitEnabled:1; /* when set, the time limit will be utilized */
+ /* 0x01 */ u32 progress:4; /* progress towards quest goal */
+ /* 0x01 */ u32 giveReward:1; /* set to true when player cannot take the item, and will skip quest completion checks */
+ /* 0x01 */ u32 unused:2;
+
+ /* 0x02 */ lbRTC_time_c timeLimit;
+} QuestBase; // size = 0xC
/* 'Not Saved' Quest */
typedef struct mQst_not_saved_c {
- /* 0x00 */ s32 work;
- /* 0x04 */ u8 h;
+ /* 0x00 */ s32 work;
+ /* 0x04 */ u8 h;
} mQst_not_saved_c; // size = 0x5
typedef struct mQst_delivery_c {
- /* 0x00 */ char unk00[0x24];
+ /* 0x00 */ char unk00[0x24];
} mQst_delivery_c; // size = 0x24
-typedef struct mQst_errand_c {
- /* 0x00 */ char unk00[0x50];
-} mQst_errand_c; // size = 0x50
+typedef struct QuestFirstJob {
+ /* 0x00 */ AnmPersonalID_c usedId[2]; /* villagers already used for first job quest (furniture, then letter) */
+ /* 0x1C */ u8 usedNum:7; /* used count for 'used_ids' */
+ /* 0x1C */ u8 wrongNum:1; /* set to TRUE if player changes out of work uniform during chores */
+} QuestFirstJob;
+
+typedef struct QuestErrandChain {
+ /* 0x00 */ AnmPersonalID_c usedId[3];
+ /* 0x24 */ u8 usedNum;
+} QuestErrandChain; // size 0x26
+
+
+typedef union ErrandInfo{
+ /* 0x00 */ QuestErrandChain chain;
+ /* 0x12 */ QuestFirstJob firstJob;
+} ErrandInfo; // size = 0x24
+
+typedef struct QuestErrand {
+ /* 0x00 */ QuestBase base; /* quest base info */
+ /* 0x0C */ AnmPersonalID_c recipient; /* villager who will receive it */
+ /* 0x1A */ AnmPersonalID_c sender; /* villager who sent it */
+ /* 0x28 */ u16 item; /* errand item */
+ /* 0x2A */ s8 pocketIdx:5; /* index in player pockets where the errand item is */
+ /* 0x2A */ s8 errandType:3; /* errand type */
+ /* 0x2C */ ErrandInfo info; /* errand type-specific data */
+} QuestErrand; // size = 0x50
+
+typedef struct QuestContest {
+ /* 0x00 */ char unk00[0x24];
+} QuestContest; // size = 0x24
+
+
+void mQst_ClearQuestInfo(QuestBase*);
+void mQst_ClearDelivery(mQst_delivery_c* deliveries, s32 count);
+void mQst_ClearErrand(QuestErrand* errands, s32 count);
+void mQst_ClearContest(QuestContest* contest);
+void mQst_ClearNotSaveQuest(mQst_not_saved_c* quest);
+// void func_800BA7E8_jp();
+// void func_800BA8A0_jp();
+// void func_800BA8F4_jp();
+// void func_800BAA10_jp();
+// void func_800BAA7C_jp();
+// void func_800BAAA4_jp();
+// void func_800BABE8_jp();
+// void func_800BAC84_jp();
+// void func_800BACEC_jp();
+// void func_800BADBC_jp();
+// void func_800BAE78_jp();
+UNK_RET mQst_CheckLimitbyPossessionIdx(s32 arg0);
+// void func_800BB0A8_jp();
+// void func_800BB0E8_jp();
+// void func_800BB10C_jp();
+// void func_800BB270_jp();
+// void func_800BB3A4_jp();
+// void func_800BB4B0_jp();
+s32 mQst_GetOccuredContestIdx(s32);
+// void func_800BB634_jp();
+// void func_800BB658_jp();
+// void func_800BB67C_jp();
+// void func_800BB6A0_jp();
+// void func_800BB6F0_jp();
+// void func_800BB740_jp();
+// void func_800BB86C_jp();
+// void func_800BB990_jp();
+// void func_800BBAB0_jp();
+void mQst_SetReceiveLetter(QuestContest*, PersonalID_c*, u8*, u16);
+QuestErrand* mQst_GetFirstJobData(void);
+// void func_800BBCBC_jp();
+// void func_800BBD00_jp();
+// void func_800BBD68_jp();
+// void func_800BBD90_jp();
+// void func_800BBDE0_jp();
+// void func_800BBE78_jp();
+// void func_800BBEE0_jp();
+// void func_800BBF3C_jp();
+// void func_800BBF98_jp();
+// void func_800BC064_jp();
+// void func_800BC10C_jp();
+// void func_800BC12C_jp();
+// void func_800BC14C_jp();
+// void func_800BC1E4_jp();
+// void func_800BC28C_jp();
+// void func_800BC33C_jp();
+// void func_800BC368_jp();
+// void func_800BC394_jp();
+s32 mQst_GetRandom(s32);
+// void func_800BC454_jp();
+// void func_800BC528_jp();
+// void func_800BC5D4_jp();
+// void func_800BC6B0_jp();
+// void func_800BC724_jp();
+// void func_800BC830_jp();
+// void mQst_PrintQuestInfo();
#endif
diff --git a/include/m_submenu.h b/include/m_submenu.h
index 069b61c..423f3dd 100644
--- a/include/m_submenu.h
+++ b/include/m_submenu.h
@@ -84,7 +84,7 @@ typedef struct Submenu {
/* 0x2C */ struct struct_8085E9B0* unk_2C;
/* 0x30 */ SubmenuMoveFunc move;
/* 0x34 */ SubmenuDrawFunc draw;
- /* 0x38 */ Mail mail;
+ /* 0x38 */ Mail_c mail;
/* 0xDC */ u8 unk_DC;
/* 0xDD */ u8 unk_DD;
/* 0xDE */ u8 unk_DE;
diff --git a/include/segment_symbols.h b/include/segment_symbols.h
index f97649e..4e169e0 100644
--- a/include/segment_symbols.h
+++ b/include/segment_symbols.h
@@ -95,5 +95,10 @@ DECLARE_SEGMENT(ac_set_ovl_gyoei);
DECLARE_SEGMENT(segment_00A58000);
+DECLARE_SEGMENT(segment_00E02000);
+DECLARE_SEGMENT(segment_00E03000);
+DECLARE_SEGMENT(segment_00E04000);
+DECLARE_SEGMENT(segment_00E0D000);
+
#endif
diff --git a/include/sys_math.h b/include/sys_math.h
index c78155c..bccf335 100644
--- a/include/sys_math.h
+++ b/include/sys_math.h
@@ -4,11 +4,13 @@
#include "ultra64.h"
#include "libc64/qrand.h"
-/* Macro to generate a random float in the range of [0, n) */
#define RANDOM_F(n) (fqrand() * (f32)(n))
+/* Macro to generate a random integer in the range of [0, n) */
+#define RANDOM(n) ((s32)RANDOM_F(n))
+#define RANDOM_F2(n) ((f32)(n) * fqrand())
/* Macro to generate a random integer in the range of [0, n) */
-#define RANDOM(n) ((int)RANDOM_F(n))
+#define RANDOM2(n) ((s32)RANDOM_F2(n))
// void reverse_u32();
// void init_rnd();
diff --git a/linker_scripts/jp/symbol_addrs_code.txt b/linker_scripts/jp/symbol_addrs_code.txt
index b520657..f1094f8 100644
--- a/linker_scripts/jp/symbol_addrs_code.txt
+++ b/linker_scripts/jp/symbol_addrs_code.txt
@@ -1201,7 +1201,7 @@ func_800829D4_jp = 0x800829D4; // type:func
func_80082B4C_jp = 0x80082B4C; // type:func
func_80082BD8_jp = 0x80082BD8; // type:func
func_80082C30_jp = 0x80082C30; // type:func
-func_80082CC8_jp = 0x80082CC8; // type:func
+mEvNM_CheckJointEvent = 0x80082CC8; // type:func
func_80082DA0_jp = 0x80082DA0; // type:func
func_80082E40_jp = 0x80082E40; // type:func
func_80082FA0_jp = 0x80082FA0; // type:func
@@ -1251,7 +1251,7 @@ func_80084CA4_jp = 0x80084CA4; // type:func
func_80084CD8_jp = 0x80084CD8; // type:func
func_80084D08_jp = 0x80084D08; // type:func
func_80084DA4_jp = 0x80084DA4; // type:func
-func_80084DE0_jp = 0x80084DE0; // type:func
+mFAs_GetFieldRank = 0x80084DE0; // type:func
mFAs_PrintFieldAssessment = 0x80084DF0; // type:func
func_80084ED0_jp = 0x80084ED0; // type:func
func_80084FAC_jp = 0x80084FAC; // type:func
@@ -1294,10 +1294,10 @@ func_8008775C_jp = 0x8008775C; // type:func
func_80087788_jp = 0x80087788; // type:func
func_800877CC_jp = 0x800877CC; // type:func
mFM_RenewalReserve = 0x800878D4; // type:func
-func_800879B0_jp = 0x800879B0; // type:func
+mFM_GetReseveName = 0x800879B0; // type:func
func_80087C30_jp = 0x80087C30; // type:func
func_80087C40_jp = 0x80087C40; // type:func
-func_80087C64_jp = 0x80087C64; // type:func
+mFI_GetBlockTopP = 0x80087C64; // type:func
mFI_GetFieldId = 0x80087C88; // type:func
func_80087C9C_jp = 0x80087C9C; // type:func
func_80087D30_jp = 0x80087D30; // type:func
@@ -1319,14 +1319,14 @@ func_80088458_jp = 0x80088458; // type:func
func_800884E0_jp = 0x800884E0; // type:func
func_800885A8_jp = 0x800885A8; // type:func
mFI_Wpos2BlockNum = 0x80088710; // type:func
-func_80088780_jp = 0x80088780; // type:func
+mFI_Wpos2BkandUtNuminBlock = 0x80088780; // type:func
func_8008883C_jp = 0x8008883C; // type:func
func_800888AC_jp = 0x800888AC; // type:func
func_80088938_jp = 0x80088938; // type:func
func_800889D8_jp = 0x800889D8; // type:func
func_80088A58_jp = 0x80088A58; // type:func
func_80088B3C_jp = 0x80088B3C; // type:func
-func_80088BC0_jp = 0x80088BC0; // type:func
+mFI_UtNum2PosXZInBk = 0x80088BC0; // type:func
func_80088BFC_jp = 0x80088BFC; // type:func
func_80088C74_jp = 0x80088C74; // type:func
func_80088CBC_jp = 0x80088CBC; // type:func
@@ -1353,7 +1353,7 @@ func_800893C8_jp = 0x800893C8; // type:func
func_80089404_jp = 0x80089404; // type:func
mFI_BlockKind2BkNum = 0x80089440; // type:func
func_800894D0_jp = 0x800894D0; // type:func
-func_80089538_jp = 0x80089538; // type:func
+mFI_GetBkNum2ColTop = 0x80089538; // type:func
func_800895B8_jp = 0x800895B8; // type:func
func_80089698_jp = 0x80089698; // type:func
func_80089704_jp = 0x80089704; // type:func
@@ -1372,7 +1372,7 @@ func_80089D6C_jp = 0x80089D6C; // type:func
func_80089E84_jp = 0x80089E84; // type:func
func_80089EF8_jp = 0x80089EF8; // type:func
func_8008A000_jp = 0x8008A000; // type:func
-func_8008A33C_jp = 0x8008A33C; // type:func
+mFI_BkNumtoUtFGTop = 0x8008A33C; // type:func
func_8008A3BC_jp = 0x8008A3BC; // type:func
func_8008A410_jp = 0x8008A410; // type:func
func_8008A4F8_jp = 0x8008A4F8; // type:func
@@ -1412,9 +1412,9 @@ func_8008BA74_jp = 0x8008BA74; // type:func
func_8008BAEC_jp = 0x8008BAEC; // type:func
func_8008BB64_jp = 0x8008BB64; // type:func
func_8008BBF0_jp = 0x8008BBF0; // type:func
-func_8008BC64_jp = 0x8008BC64; // type:func
+mFI_SetMoveActorBitData_ON = 0x8008BC64; // type:func
func_8008BCFC_jp = 0x8008BCFC; // type:func
-func_8008BD98_jp = 0x8008BD98; // type:func
+mFI_MyMoveActorBitData_ON = 0x8008BD98; // type:func
func_8008BDCC_jp = 0x8008BDCC; // type:func
func_8008BE00_jp = 0x8008BE00; // type:func
func_8008BE38_jp = 0x8008BE38; // type:func
@@ -1424,14 +1424,14 @@ func_8008C058_jp = 0x8008C058; // type:func
mFI_CheckPlayerWade = 0x8008C0FC; // type:func
func_8008C120_jp = 0x8008C120; // type:func
func_8008C130_jp = 0x8008C130; // type:func
-func_8008C1E0_jp = 0x8008C1E0; // type:func
+mFI_GetDepositP = 0x8008C1E0; // type:func
func_8008C344_jp = 0x8008C344; // type:func
func_8008C390_jp = 0x8008C390; // type:func
func_8008C3B0_jp = 0x8008C3B0; // type:func
func_8008C3D4_jp = 0x8008C3D4; // type:func
func_8008C3E8_jp = 0x8008C3E8; // type:func
func_8008C458_jp = 0x8008C458; // type:func
-func_8008C478_jp = 0x8008C478; // type:func
+mFI_BlockDepositOFF = 0x8008C478; // type:func
func_8008C498_jp = 0x8008C498; // type:func
func_8008C4B8_jp = 0x8008C4B8; // type:func
func_8008C504_jp = 0x8008C504; // type:func
@@ -1595,7 +1595,7 @@ func_80092B8C_jp = 0x80092B8C; // type:func
func_80092BA0_jp = 0x80092BA0; // type:func
func_80092BE8_jp = 0x80092BE8; // type:func
mHsRm_GetHuusuiRoom = 0x80092C2C; // type:func
-func_80092D10_jp = 0x80092D10; // type:func
+mHandbill_Set_free_str = 0x80092D10; // type:func
func_80092E14_jp = 0x80092E14; // type:func
func_80092E80_jp = 0x80092E80; // type:func
func_80092FC4_jp = 0x80092FC4; // type:func
@@ -1629,14 +1629,14 @@ func_800939B8_jp = 0x800939B8; // type:func
func_80093B28_jp = 0x80093B28; // type:func
func_80093C98_jp = 0x80093C98; // type:func
func_80093DA8_jp = 0x80093DA8; // type:func
-func_80093F04_jp = 0x80093F04; // type:func
-func_80093F54_jp = 0x80093F54; // type:func
+mHandbill_Load_HandbillFromRom = 0x80093F04; // type:func
+mHandbill_Load_HandbillFromRom2 = 0x80093F54; // type:func
func_80093F94_jp = 0x80093F94; // type:func
func_800940A8_jp = 0x800940A8; // type:func
func_800941B0_jp = 0x800941B0; // type:func
func_800942A0_jp = 0x800942A0; // type:func
func_80094400_jp = 0x80094400; // type:func
-func_800944B8_jp = 0x800944B8; // type:func
+mHandbillz_load = 0x800944B8; // type:func
func_80094520_jp = 0x80094520; // type:func
func_80094690_jp = 0x80094690; // type:func
mHm_SetNowHome = 0x800946D0; // type:func
@@ -1654,18 +1654,18 @@ func_80094C44_jp = 0x80094C44; // type:func
func_80094CAC_jp = 0x80094CAC; // type:func
func_80094DD0_jp = 0x80094DD0; // type:func
func_80094E10_jp = 0x80094E10; // type:func
-func_80094E38_jp = 0x80094E38; // type:func
-func_80094E90_jp = 0x80094E90; // type:func
-func_80094EE0_jp = 0x80094EE0; // type:func
+mLd_CheckCmpLandName = 0x80094E38; // type:func
+mLd_CheckCmpLand = 0x80094E90; // type:func
+mLd_ClearLandName = 0x80094EE0; // type:func
mLd_CopyLandName = 0x80094F04; // type:func
func_80094F24_jp = 0x80094F24; // type:func
func_80094F84_jp = 0x80094F84; // type:func
func_8009504C_jp = 0x8009504C; // type:func
-func_800950D8_jp = 0x800950D8; // type:func
+mLd_GetLandName = 0x800950D8; // type:func
func_800950E8_jp = 0x800950E8; // type:func
func_8009519C_jp = 0x8009519C; // type:func
mLd_PlayerManKindCheck = 0x800951C0; // type:func
-func_800951E4_jp = 0x800951E4; // type:func
+mLd_CheckThisLand = 0x800951E4; // type:func
func_80095218_jp = 0x80095218; // type:func
mLd_LandDataInit = 0x8009524C; // type:func
func_80095280_jp = 0x80095280; // type:func
@@ -1703,7 +1703,7 @@ func_800965F4_jp = 0x800965F4; // type:func
func_800966D8_jp = 0x800966D8; // type:func
func_800966E0_jp = 0x800966E0; // type:func
func_80096710_jp = 0x80096710; // type:func
-func_80096740_jp = 0x80096740; // type:func
+mIN_copy_name_str = 0x80096740; // type:func
func_80096860_jp = 0x80096860; // type:func
func_800968C0_jp = 0x800968C0; // type:func
func_80096B2C_jp = 0x80096B2C; // type:func
@@ -1885,7 +1885,7 @@ mMl_get_npcinfo_from_mail_name = 0x8009C780; // type:func
mMl_hunt_for_send_address = 0x8009C80C; // type:func
mMl_check_send_mail = 0x8009C89C; // type:func
mMl_check_set_present_myself = 0x8009C8C0; // type:func
-func_8009C900_jp = 0x8009C900; // type:func
+mMC_get_mail_hit_rate = 0x8009C900; // type:func
func_8009C9F0_jp = 0x8009C9F0; // type:func
func_8009CA54_jp = 0x8009CA54; // type:func
func_8009CA94_jp = 0x8009CA94; // type:func
@@ -2242,43 +2242,43 @@ func_800A63F8_jp = 0x800A63F8; // type:func
func_800A6450_jp = 0x800A6450; // type:func
func_800A6548_jp = 0x800A6548; // type:func
func_800A65C4_jp = 0x800A65C4; // type:func
-func_800A6810_jp = 0x800A6810; // type:func
-func_800A6920_jp = 0x800A6920; // type:func
-func_800A6940_jp = 0x800A6940; // type:func
-func_800A695C_jp = 0x800A695C; // type:func
+mNpc_MakeRandTable = 0x800A6810; // type:func
+mNpc_ClearBufSpace1 = 0x800A6920; // type:func
+mNpc_AddNowNpcMax = 0x800A6940; // type:func
+mNpc_SubNowNpcMax = 0x800A695C; // type:func
mNpc_ClearAnimalPersonalID = 0x800A6978; // type:func
mNpc_CheckFreeAnimalPersonalID = 0x800A69C8; // type:func
mNpc_CopyAnimalPersonalID = 0x800A6A04; // type:func
mNpc_CheckCmpAnimalPersonalID = 0x800A6A6C; // type:func
-func_800A6AF0_jp = 0x800A6AF0; // type:func
-func_800A6B58_jp = 0x800A6B58; // type:func
-func_800A6B6C_jp = 0x800A6B6C; // type:func
-func_800A6B7C_jp = 0x800A6B7C; // type:func
-func_800A6B9C_jp = 0x800A6B9C; // type:func
-func_800A6BC8_jp = 0x800A6BC8; // type:func
-func_800A6C1C_jp = 0x800A6C1C; // type:func
-func_800A6C84_jp = 0x800A6C84; // type:func
-func_800A6CE4_jp = 0x800A6CE4; // type:func
-func_800A6D04_jp = 0x800A6D04; // type:func
-func_800A6DB0_jp = 0x800A6DB0; // type:func
-func_800A6DD0_jp = 0x800A6DD0; // type:func
-func_800A6E0C_jp = 0x800A6E0C; // type:func
+mNpc_GetAnimalNum = 0x800A6AF0; // type:func
+mNpc_CheckRemoveExp = 0x800A6B58; // type:func
+mNpc_GetRemoveTime = 0x800A6B6C; // type:func
+mNpc_AddRemoveTime = 0x800A6B7C; // type:func
+mNpc_SetRemoveExp = 0x800A6B9C; // type:func
+mNpc_SetParentName = 0x800A6BC8; // type:func
+mNpc_SetParentNameAllAnimal = 0x800A6C1C; // type:func
+mNpc_ClearAnimalMail = 0x800A6C84; // type:func
+mNpc_CopyAnimalMail = 0x800A6CE4; // type:func
+mNpc_ClearAnimalMemory = 0x800A6D04; // type:func
+mNpc_CopyAnimalMemory = 0x800A6DB0; // type:func
+mNpc_AddFriendship = 0x800A6DD0; // type:func
+mNpc_CheckFreeAnimalMemory = 0x800A6E0C; // type:func
mNpc_RenewalAnimalMemory = 0x800A6E40; // type:func
-func_800A6F48_jp = 0x800A6F48; // type:func
-func_800A6FF4_jp = 0x800A6FF4; // type:func
-func_800A706C_jp = 0x800A706C; // type:func
-func_800A71AC_jp = 0x800A71AC; // type:func
-func_800A71F8_jp = 0x800A71F8; // type:func
-func_800A7238_jp = 0x800A7238; // type:func
-func_800A72C0_jp = 0x800A72C0; // type:func
-func_800A73D8_jp = 0x800A73D8; // type:func
-func_800A74A0_jp = 0x800A74A0; // type:func
-func_800A7530_jp = 0x800A7530; // type:func
-func_800A75FC_jp = 0x800A75FC; // type:func
-func_800A76E4_jp = 0x800A76E4; // type:func
-func_800A77F0_jp = 0x800A77F0; // type:func
-func_800A7858_jp = 0x800A7858; // type:func
-func_800A78DC_jp = 0x800A78DC; // type:func
+mNpc_GetOldAnimalMemoryIdx = 0x800A6F48; // type:func
+mNpc_GetFreeAnimalMemoryIdx = 0x800A6FF4; // type:func
+mNpc_ForceGetFreeAnimalMemoryIdx = 0x800A706C; // type:func
+mNpc_SetAnimalMemory_NotSetDay = 0x800A71AC; // type:func
+mNpc_SetAnimalMemory = 0x800A71F8; // type:func
+mNpc_GetAnimalMemoryIdx = 0x800A7238; // type:func
+mNpc_SetAnimalLastTalk = 0x800A72C0; // type:func
+mNpc_SetAnimalPersonalID2Memory = 0x800A73D8; // type:func
+mNpc_GetHighestFriendshipIdx = 0x800A74A0; // type:func
+mNpc_SelectBestFriend = 0x800A7530; // type:func
+mNpc_GetAnimalMemoryBestFriend = 0x800A75FC; // type:func
+mNpc_GetAnimalMemoryFriend_Land_Sex = 0x800A76E4; // type:func
+mNpc_GetAnimalMemoryNum = 0x800A77F0; // type:func
+mNpc_GetAnimalMemoryLetterNum = 0x800A7858; // type:func
+mNpc_GetAnimalMemoryLandKindNum = 0x800A78DC; // type:func
mNpc_ClearAnimalInfo = 0x800A7A04; // type:func
mNpc_ClearAnyAnimalInfo = 0x800A7A9C; // type:func
mNpc_CheckFreeAnimalInfo = 0x800A7AEC; // type:func
@@ -2286,155 +2286,155 @@ mNpc_GetFreeAnimalInfo = 0x800A7B34; // type:func
mNpc_UseFreeAnimalInfo = 0x800A7BAC; // type:func
mNpc_CopyAnimalInfo = 0x800A7C10; // type:func
mNpc_SearchAnimalinfo = 0x800A7C30; // type:func
-func_800A7C94_jp = 0x800A7C94; // type:func
-func_800A7D08_jp = 0x800A7D08; // type:func
-func_800A7DA0_jp = 0x800A7DA0; // type:func
+mNpc_GetAnimalInfoP = 0x800A7C94; // type:func
+mNpc_SearchAnimalPersonalID = 0x800A7D08; // type:func
+mNpc_GetOtherAnimalPersonalIDOtherBlock = 0x800A7DA0; // type:func
mNpc_GetOtherAnimalPersonalID = 0x800A80B0; // type:func
-func_800A80D8_jp = 0x800A80D8; // type:func
-func_800A8148_jp = 0x800A8148; // type:func
-func_800A820C_jp = 0x800A820C; // type:func
-func_800A82C8_jp = 0x800A82C8; // type:func
-func_800A8344_jp = 0x800A8344; // type:func
-func_800A83F0_jp = 0x800A83F0; // type:func
-func_800A845C_jp = 0x800A845C; // type:func
-func_800A8614_jp = 0x800A8614; // type:func
-func_800A86C4_jp = 0x800A86C4; // type:func
-func_800A86E8_jp = 0x800A86E8; // type:func
-func_800A8764_jp = 0x800A8764; // type:func
-func_800A8814_jp = 0x800A8814; // type:func
-func_800A8868_jp = 0x800A8868; // type:func
-func_800A8AB4_jp = 0x800A8AB4; // type:func
-func_800A8B10_jp = 0x800A8B10; // type:func
-func_800A8B84_jp = 0x800A8B84; // type:func
-func_800A8C48_jp = 0x800A8C48; // type:func
-func_800A8DB4_jp = 0x800A8DB4; // type:func
-func_800A8F30_jp = 0x800A8F30; // type:func
-func_800A9028_jp = 0x800A9028; // type:func
-func_800A9110_jp = 0x800A9110; // type:func
-func_800A918C_jp = 0x800A918C; // type:func
-func_800A91DC_jp = 0x800A91DC; // type:func
-func_800A9364_jp = 0x800A9364; // type:func
-func_800A93AC_jp = 0x800A93AC; // type:func
-func_800A9468_jp = 0x800A9468; // type:func
-func_800A94C8_jp = 0x800A94C8; // type:func
-func_800A956C_jp = 0x800A956C; // type:func
-func_800A96B0_jp = 0x800A96B0; // type:func
-func_800A9780_jp = 0x800A9780; // type:func
-func_800A992C_jp = 0x800A992C; // type:func
-func_800A99B8_jp = 0x800A99B8; // type:func
-func_800A9A98_jp = 0x800A9A98; // type:func
-func_800A9BC4_jp = 0x800A9BC4; // type:func
-func_800A9BD4_jp = 0x800A9BD4; // type:func
-func_800A9CD4_jp = 0x800A9CD4; // type:func
-func_800A9D68_jp = 0x800A9D68; // type:func
-func_800A9E54_jp = 0x800A9E54; // type:func
-func_800A9E7C_jp = 0x800A9E7C; // type:func
-func_800A9EC8_jp = 0x800A9EC8; // type:func
-func_800A9F9C_jp = 0x800A9F9C; // type:func
-func_800AA028_jp = 0x800AA028; // type:func
-func_800AA0B8_jp = 0x800AA0B8; // type:func
-func_800AA124_jp = 0x800AA124; // type:func
-func_800AA14C_jp = 0x800AA14C; // type:func
+mNpc_SetAnimalThisLand = 0x800A80D8; // type:func
+mNpc_GetSameLooksNum = 0x800A8148; // type:func
+mNpc_CheckNpcExistBlock = 0x800A820C; // type:func
+mNpc_Mail2AnimalMail = 0x800A82C8; // type:func
+mNpc_AnimalMail2Mail = 0x800A8344; // type:func
+mNpc_CheckMailChar = 0x800A83F0; // type:func
+mNpc_CheckNormalMail_sub = 0x800A845C; // type:func
+mNpc_CheckNormalMail_length = 0x800A8614; // type:func
+mNpc_CheckNormalMail = 0x800A86C4; // type:func
+mNpc_SetMailCondThisLand = 0x800A86E8; // type:func
+mNpc_SetMailCondOtherLand = 0x800A8764; // type:func
+mNpc_SetRemailCond = 0x800A8814; // type:func
+mNpc_SendMailtoNpc = 0x800A8868; // type:func
+mNpc_ClearRemail = 0x800A8AB4; // type:func
+mNpc_GetRemailPresent = 0x800A8B10; // type:func
+mNpc_GetHandbillz = 0x800A8B84; // type:func
+mNpc_SetRemailFreeString = 0x800A8C48; // type:func
+mNpc_GetRemailGoodData = 0x800A8DB4; // type:func
+mNpc_GetRemailWrongData = 0x800A8F30; // type:func
+mNpc_GetRemailData = 0x800A9028; // type:func
+mNpc_SendRemailPostOffice = 0x800A9110; // type:func
+mNpc_CheckLetterTime = 0x800A918C; // type:func
+mNpc_Remail = 0x800A91DC; // type:func
+mNpc_GetPaperType = 0x800A9364; // type:func
+mNpc_LoadMailDataCommon2 = 0x800A93AC; // type:func
+mNpc_GetEventPresent = 0x800A9468; // type:func
+mNpc_GetEventMail = 0x800A94C8; // type:func
+mNpc_SendEventPresentMail = 0x800A956C; // type:func
+mNpc_SendEventPresentMailSex = 0x800A96B0; // type:func
+mNpc_SendEventPresentMail_common = 0x800A9780; // type:func
+mNpc_GetBirthdayPresent = 0x800A992C; // type:func
+mNpc_GetBirthdayCard = 0x800A99B8; // type:func
+mNpc_SendBirthdayCard = 0x800A9A98; // type:func
+mNpc_SendEventBirthdayCard = 0x800A9BC4; // type:func
+mNpc_SendEventBirthdayCard2 = 0x800A9BD4; // type:func
+mNpc_GetXmasCardData = 0x800A9CD4; // type:func
+mNpc_SendEventXmasCard = 0x800A9D68; // type:func
+mNpc_SetWordEnding = 0x800A9E54; // type:func
+mNpc_GetWordEnding = 0x800A9E7C; // type:func
+mNpc_ResetWordEnding = 0x800A9EC8; // type:func
+mNpc_GetFreeEventNpcIdx = 0x800A9F9C; // type:func
+mNpc_RegistEventNpc = 0x800AA028; // type:func
+mNpc_UnRegistEventNpc = 0x800AA0B8; // type:func
+mNpc_ClearEventNpc = 0x800AA124; // type:func
+mNpc_GetSameEventNpc = 0x800AA14C; // type:func
mNpc_GetLooks = 0x800AA1E0; // type:func
-func_800AA218_jp = 0x800AA218; // type:func
-func_800AA29C_jp = 0x800AA29C; // type:func
-func_800AA2F8_jp = 0x800AA2F8; // type:func
-func_800AA35C_jp = 0x800AA35C; // type:func
-func_800AA3A4_jp = 0x800AA3A4; // type:func
-func_800AA438_jp = 0x800AA438; // type:func
-func_800AA49C_jp = 0x800AA49C; // type:func
-func_800AA4FC_jp = 0x800AA4FC; // type:func
-func_800AA51C_jp = 0x800AA51C; // type:func
+mNpc_SetDefAnimalInfo = 0x800AA218; // type:func
+mNpc_SetDefAnimal = 0x800AA29C; // type:func
+mNpc_SetHaveAppeared = 0x800AA2F8; // type:func
+mNpc_GetHaveAppeared_idx = 0x800AA35C; // type:func
+mNpc_GetLooks2NotHaveAppearedNum = 0x800AA3A4; // type:func
+mNpc_ResetHaveAppeared_common = 0x800AA438; // type:func
+mNpc_ResetHaveAppeared = 0x800AA49C; // type:func
+mNpc_GetDefGrowPermission = 0x800AA4FC; // type:func
+mNpc_DecideLivingNpcMax = 0x800AA51C; // type:func
mNpc_SetAnimalTitleDemo = 0x800AA790; // type:func
-func_800AA8C4_jp = 0x800AA8C4; // type:func
-func_800AA9F4_jp = 0x800AA9F4; // type:func
-func_800AAA40_jp = 0x800AAA40; // type:func
-func_800AAB48_jp = 0x800AAB48; // type:func
-func_800AAC88_jp = 0x800AAC88; // type:func
-func_800AADE8_jp = 0x800AADE8; // type:func
-func_800AAEFC_jp = 0x800AAEFC; // type:func
-func_800AB054_jp = 0x800AB054; // type:func
-func_800AB09C_jp = 0x800AB09C; // type:func
+mNpc_GetReservedUtNum = 0x800AA8C4; // type:func
+mNpc_BlockNum2ReservedUtNum = 0x800AA9F4; // type:func
+mNpc_MakeReservedListBeforeFieldct = 0x800AAA40; // type:func
+mNpc_MakeReservedListAfterFieldct = 0x800AAB48; // type:func
+mNpc_BuildHouseBeforeFieldct = 0x800AAC88; // type:func
+mNpc_DestroyHouse = 0x800AADE8; // type:func
+mNpc_SetNpcHome = 0x800AAEFC; // type:func
+mNpc_InitNpcData = 0x800AB054; // type:func
+mNpc_InitNpcList = 0x800AB09C; // type:func
mNpc_SetNpcList = 0x800AB134; // type:func
mNpc_SetNpcinfo = 0x800AB3A0; // type:func
-func_800AB498_jp = 0x800AB498; // type:func
-func_800AB62C_jp = 0x800AB62C; // type:func
-func_800AB6C8_jp = 0x800AB6C8; // type:func
-func_800AB734_jp = 0x800AB734; // type:func
-func_800AB7D0_jp = 0x800AB7D0; // type:func
-func_800AB80C_jp = 0x800AB80C; // type:func
+mNpc_AddNpc_inNpcRoom = 0x800AB498; // type:func
+mNpc_RenewalNpcRoom = 0x800AB62C; // type:func
+mNpc_RenewalSetNpc = 0x800AB6C8; // type:func
+mNpc_GetFriendAnimalNum = 0x800AB734; // type:func
+mNpc_CheckFriendAllAnimal = 0x800AB7D0; // type:func
+mNpc_CheckSelectFurniture = 0x800AB80C; // type:func
func_800AB8A0_jp = 0x800AB8A0; // type:func
-func_800ABA14_jp = 0x800ABA14; // type:func
-func_800ABAA8_jp = 0x800ABAA8; // type:func
-func_800ABAF0_jp = 0x800ABAF0; // type:func
+mNpc_SetNpcFurnitureRandom = 0x800ABA14; // type:func
+mNpc_GetNpcFurniture = 0x800ABAA8; // type:func
+mNpc_ClearInAnimal = 0x800ABAF0; // type:func
mNpc_GetInAnimalP = 0x800ABB14; // type:func
-func_800ABB24_jp = 0x800ABB24; // type:func
-func_800ABCF8_jp = 0x800ABCF8; // type:func
+mNpc_DecideRemoveAnimalNo_Friend = 0x800ABB24; // type:func
+mNpc_DecideRemoveAnimalNo = 0x800ABCF8; // type:func
mNpc_SetRemoveAnimalNo = 0x800ABD90; // type:func
-func_800ABE30_jp = 0x800ABE30; // type:func
-func_800ABF40_jp = 0x800ABF40; // type:func
-func_800AC1A0_jp = 0x800AC1A0; // type:func
-func_800AC1C8_jp = 0x800AC1C8; // type:func
-func_800AC1EC_jp = 0x800AC1EC; // type:func
-func_800AC284_jp = 0x800AC284; // type:func
-func_800AC358_jp = 0x800AC358; // type:func
-func_800AC488_jp = 0x800AC488; // type:func
+mNpc_CheckGoodbyAnimalMemoryNum = 0x800ABE30; // type:func
+mNpc_GetGoodbyAnimalIdx = 0x800ABF40; // type:func
+mNpc_ClearGoodbyMail = 0x800AC1A0; // type:func
+mNpc_FirstClearGoodbyMail = 0x800AC1C8; // type:func
+mNpc_SetGoodbyAnimalMail = 0x800AC1EC; // type:func
+mNpc_SetGoodbyMailData = 0x800AC284; // type:func
+mNpc_SendGoodbyAnimalMailOne = 0x800AC358; // type:func
+mNpc_SendGoodbyAnimalMail = 0x800AC488; // type:func
mNpc_SendRegisteredGoodbyMail = 0x800AC558; // type:func
-func_800AC57C_jp = 0x800AC57C; // type:func
-func_800AC804_jp = 0x800AC804; // type:func
+mNpc_GetRemoveAnimal = 0x800AC57C; // type:func
+mNpc_CheckBuildHouse = 0x800AC804; // type:func
mNpc_SetReturnAnimal = 0x800AC898; // type:func
-func_800ACB24_jp = 0x800ACB24; // type:func
-func_800ACB54_jp = 0x800ACB54; // type:func
-func_800ACC38_jp = 0x800ACC38; // type:func
-func_800ACCAC_jp = 0x800ACCAC; // type:func
+mNpc_AddActor_inBlock = 0x800ACB24; // type:func
+mNpc_SetNpcNameID = 0x800ACB54; // type:func
+mNpc_LoadNpcNameString = 0x800ACC38; // type:func
+mNpc_GetNpcWorldNameTableNo = 0x800ACCAC; // type:func
mNpc_GetNpcWorldNameAnm = 0x800ACD18; // type:func
-func_800ACD74_jp = 0x800ACD74; // type:func
-func_800ACDF8_jp = 0x800ACDF8; // type:func
-func_800ACE90_jp = 0x800ACE90; // type:func
+mNpc_GetNpcWorldNameP = 0x800ACD74; // type:func
+mNpc_GetNpcWorldName = 0x800ACDF8; // type:func
+mNpc_GetRandomAnimalName = 0x800ACE90; // type:func
mNpc_GetAnimalPlateName = 0x800ACF84; // type:func
-func_800AD084_jp = 0x800AD084; // type:func
-func_800AD0B8_jp = 0x800AD0B8; // type:func
-func_800AD104_jp = 0x800AD104; // type:func
-func_800AD154_jp = 0x800AD154; // type:func
-func_800AD188_jp = 0x800AD188; // type:func
-func_800AD1E0_jp = 0x800AD1E0; // type:func
-func_800AD22C_jp = 0x800AD22C; // type:func
-func_800AD2B8_jp = 0x800AD2B8; // type:func
+mNpc_GetNpcLooks = 0x800AD084; // type:func
+mNpc_GetActorSex = 0x800AD0B8; // type:func
+mNpc_GetLooks2Sex = 0x800AD104; // type:func
+mNpc_GetAnimalSex = 0x800AD154; // type:func
+mNpc_GetNpcSex = 0x800AD188; // type:func
+mNpc_GetNpcSoundSpecNotAnimal = 0x800AD1E0; // type:func
+mNpc_GetNpcSoundSpec = 0x800AD22C; // type:func
+mNpc_GetMsg = 0x800AD2B8; // type:func
mNpc_InitNpcAllInfo = 0x800AD2C4; // type:func
-func_800AD338_jp = 0x800AD338; // type:func
-func_800AD3BC_jp = 0x800AD3BC; // type:func
-func_800AD4B8_jp = 0x800AD4B8; // type:func
-func_800AD614_jp = 0x800AD614; // type:func
-func_800AD6D4_jp = 0x800AD6D4; // type:func
-func_800AD8C4_jp = 0x800AD8C4; // type:func
-func_800AD954_jp = 0x800AD954; // type:func
-func_800AD9FC_jp = 0x800AD9FC; // type:func
-func_800ADBE4_jp = 0x800ADBE4; // type:func
-func_800ADC28_jp = 0x800ADC28; // type:func
-func_800ADC8C_jp = 0x800ADC8C; // type:func
-func_800ADD20_jp = 0x800ADD20; // type:func
-func_800ADEFC_jp = 0x800ADEFC; // type:func
-func_800AE110_jp = 0x800AE110; // type:func
+mNpc_CheckGrowFieldRank = 0x800AD338; // type:func
+mNpc_CheckGrow = 0x800AD3BC; // type:func
+mNpc_GetMinLooks = 0x800AD4B8; // type:func
+mNpc_GetMinSex = 0x800AD614; // type:func
+mNpc_GrowLooksNpcIdx = 0x800AD6D4; // type:func
+mNpc_SetAnimalInfoNpcIdx = 0x800AD8C4; // type:func
+mNpc_SetGrowNpc = 0x800AD954; // type:func
+mNpc_Grow = 0x800AD9FC; // type:func
+mNpc_CheckNpcSet_fgcol = 0x800ADBE4; // type:func
+mNpc_CheckNpcSet_fgcol_hard = 0x800ADC28; // type:func
+mNpc_CheckNpcSet = 0x800ADC8C; // type:func
+mNpc_GetMakeUtNuminBlock_hard_area = 0x800ADD20; // type:func
+mNpc_GetMakeUtNuminBlock_area = 0x800ADEFC; // type:func
+mNpc_GetMakeUtNuminBlock = 0x800AE110; // type:func
mNpc_ClearTalkInfo = 0x800AE134; // type:func
-func_800AE1A0_jp = 0x800AE1A0; // type:func
-func_800AE1B8_jp = 0x800AE1B8; // type:func
-func_800AE1D8_jp = 0x800AE1D8; // type:func
-func_800AE23C_jp = 0x800AE23C; // type:func
-func_800AE284_jp = 0x800AE284; // type:func
-func_800AE2E8_jp = 0x800AE2E8; // type:func
-func_800AE320_jp = 0x800AE320; // type:func
-func_800AE37C_jp = 0x800AE37C; // type:func
-func_800AE3B4_jp = 0x800AE3B4; // type:func
-func_800AE4B4_jp = 0x800AE4B4; // type:func
-func_800AE558_jp = 0x800AE558; // type:func
-func_800AE5C8_jp = 0x800AE5C8; // type:func
-func_800AE64C_jp = 0x800AE64C; // type:func
-func_800AE670_jp = 0x800AE670; // type:func
-func_800AE694_jp = 0x800AE694; // type:func
-func_800AE6B0_jp = 0x800AE6B0; // type:func
-func_800AE6CC_jp = 0x800AE6CC; // type:func
-func_800AE76C_jp = 0x800AE76C; // type:func
-func_800AE898_jp = 0x800AE898; // type:func
+mNpc_TimerCountDown = 0x800AE1A0; // type:func
+mNpc_SetUnlockTimer = 0x800AE1B8; // type:func
+mNpc_CountTalkNum = 0x800AE1D8; // type:func
+mNpc_CheckOverImpatient = 0x800AE23C; // type:func
+mNpc_GetOverImpatient = 0x800AE284; // type:func
+mNpc_CheckQuestRequest = 0x800AE2E8; // type:func
+mNpc_SetQuestRequestOFF = 0x800AE320; // type:func
+mNpc_UnlockTimerCountDown = 0x800AE37C; // type:func
+mNpc_TalkInfoMove = 0x800AE3B4; // type:func
+mNpc_TalkEndMove = 0x800AE4B4; // type:func
+mNpc_GetNpcFloorNo = 0x800AE558; // type:func
+mNpc_SetTalkBee = 0x800AE5C8; // type:func
+mNpc_GetFishCompleteTalk = 0x800AE64C; // type:func
+mNpc_GetInsectCompleteTalk = 0x800AE670; // type:func
+mNpc_SetFishCompleteTalk = 0x800AE694; // type:func
+mNpc_SetInsectCompleteTalk = 0x800AE6B0; // type:func
+mNpc_SetNpcHomeYpos = 0x800AE6CC; // type:func
+mNpc_PrintRemoveInfo = 0x800AE76C; // type:func
+mNpc_SetTalkAnimalIdx_fdebug = 0x800AE898; // type:func
mNpc_PrintFriendship_fdebug = 0x800AE8C8; // type:func
mNPS_get_schedule_area = 0x800AEA80; // type:func
mNPS_set_schedule_area = 0x800AEB50; // type:func
@@ -2685,9 +2685,9 @@ func_800B66CC_jp = 0x800B66CC; // type:func
mPB_police_box_init = 0x800B6718; // type:func
func_800B67C0_jp = 0x800B67C0; // type:func
func_800B6838_jp = 0x800B6838; // type:func
-func_800B68E8_jp = 0x800B68E8; // type:func
+mPO_get_keep_mail_sum = 0x800B68E8; // type:func
func_800B690C_jp = 0x800B690C; // type:func
-func_800B6A3C_jp = 0x800B6A3C; // type:func
+mPO_receipt_proc = 0x800B6A3C; // type:func
func_800B6AC8_jp = 0x800B6AC8; // type:func
func_800B6B94_jp = 0x800B6B94; // type:func
func_800B6C14_jp = 0x800B6C14; // type:func
@@ -2711,12 +2711,12 @@ func_800B7560_jp = 0x800B7560; // type:func
mPO_business_proc = 0x800B7624; // type:func
func_800B7680_jp = 0x800B7680; // type:func
func_800B7700_jp = 0x800B7700; // type:func
-func_800B7780_jp = 0x800B7780; // type:func
+mPr_ClearPlayerName = 0x800B7780; // type:func
mPr_CopyPlayerName = 0x800B77A4; // type:func
-func_800B77C4_jp = 0x800B77C4; // type:func
+mPr_NullCheckPlayerName = 0x800B77C4; // type:func
func_800B7804_jp = 0x800B7804; // type:func
func_800B785C_jp = 0x800B785C; // type:func
-func_800B7914_jp = 0x800B7914; // type:func
+mPr_NullCheckPersonalID = 0x800B7914; // type:func
mPr_ClearPersonalID = 0x800B795C; // type:func
func_800B7998_jp = 0x800B7998; // type:func
mPr_CopyPersonalID = 0x800B79E0; // type:func
@@ -2733,7 +2733,7 @@ func_800B7F00_jp = 0x800B7F00; // type:func
func_800B7F48_jp = 0x800B7F48; // type:func
mPr_CheckPrivate = 0x800B7F78; // type:func
func_800B7FA0_jp = 0x800B7FA0; // type:func
-func_800B7FD4_jp = 0x800B7FD4; // type:func
+mPr_GetPrivateIdx = 0x800B7FD4; // type:func
func_800B8068_jp = 0x800B8068; // type:func
func_800B80B4_jp = 0x800B80B4; // type:func
func_800B8128_jp = 0x800B8128; // type:func
@@ -2796,10 +2796,10 @@ func_800BA3D0_jp = 0x800BA3D0; // type:func
mPr_RenewalMapInfo = 0x800BA404; // type:func
mPr_RandomSetPlayerData_title_demo = 0x800BA494; // type:func
mPr_PrintMapInfo_debug = 0x800BA50C; // type:func
-func_800BA660_jp = 0x800BA660; // type:func
+mQst_ClearQuestInfo = 0x800BA660; // type:func
mQst_ClearDelivery = 0x800BA690; // type:func
mQst_ClearErrand = 0x800BA6F0; // type:func
-func_800BA778_jp = 0x800BA778; // type:func
+mQst_ClearContest = 0x800BA778; // type:func
mQst_ClearNotSaveQuest = 0x800BA7C8; // type:func
func_800BA7E8_jp = 0x800BA7E8; // type:func
func_800BA8A0_jp = 0x800BA8A0; // type:func
@@ -2819,7 +2819,7 @@ func_800BB10C_jp = 0x800BB10C; // type:func
func_800BB270_jp = 0x800BB270; // type:func
func_800BB3A4_jp = 0x800BB3A4; // type:func
func_800BB4B0_jp = 0x800BB4B0; // type:func
-func_800BB5DC_jp = 0x800BB5DC; // type:func
+mQst_GetOccuredContestIdx = 0x800BB5DC; // type:func
func_800BB634_jp = 0x800BB634; // type:func
func_800BB658_jp = 0x800BB658; // type:func
func_800BB67C_jp = 0x800BB67C; // type:func
@@ -2829,8 +2829,8 @@ func_800BB740_jp = 0x800BB740; // type:func
func_800BB86C_jp = 0x800BB86C; // type:func
func_800BB990_jp = 0x800BB990; // type:func
func_800BBAB0_jp = 0x800BBAB0; // type:func
-func_800BBB30_jp = 0x800BBB30; // type:func
-func_800BBBEC_jp = 0x800BBBEC; // type:func
+mQst_SetReceiveLetter = 0x800BBB30; // type:func
+mQst_GetFirstJobData = 0x800BBBEC; // type:func
func_800BBCBC_jp = 0x800BBCBC; // type:func
func_800BBD00_jp = 0x800BBD00; // type:func
func_800BBD68_jp = 0x800BBD68; // type:func
@@ -2849,7 +2849,7 @@ func_800BC28C_jp = 0x800BC28C; // type:func
func_800BC33C_jp = 0x800BC33C; // type:func
func_800BC368_jp = 0x800BC368; // type:func
func_800BC394_jp = 0x800BC394; // type:func
-func_800BC414_jp = 0x800BC414; // type:func
+mQst_GetRandom = 0x800BC414; // type:func
func_800BC454_jp = 0x800BC454; // type:func
func_800BC528_jp = 0x800BC528; // type:func
func_800BC5D4_jp = 0x800BC5D4; // type:func
@@ -2947,7 +2947,7 @@ func_800BFA78_jp = 0x800BFA78; // type:func
func_800BFAA8_jp = 0x800BFAA8; // type:func
func_800BFC00_jp = 0x800BFC00; // type:func
func_800BFC5C_jp = 0x800BFC5C; // type:func
-func_800BFCF0_jp = 0x800BFCF0; // type:func
+mSP_SelectRandomItem_New = 0x800BFCF0; // type:func
func_800BFF8C_jp = 0x800BFF8C; // type:func
func_800BFFC0_jp = 0x800BFFC0; // type:func
func_800C0194_jp = 0x800C0194; // type:func
@@ -2998,7 +2998,7 @@ func_800C2480_jp = 0x800C2480; // type:func
func_800C2578_jp = 0x800C2578; // type:func
func_800C2718_jp = 0x800C2718; // type:func
func_800C284C_jp = 0x800C284C; // type:func
-func_800C297C_jp = 0x800C297C; // type:func
+mSP_RandomUmbSelect = 0x800C297C; // type:func
func_800C2AAC_jp = 0x800C2AAC; // type:func
func_800C2B70_jp = 0x800C2B70; // type:func
func_800C2CC8_jp = 0x800C2CC8; // type:func
@@ -3025,7 +3025,7 @@ mSDI_StartInitAfter = 0x800C3BCC; // type:func
mSDI_StartInitBefore = 0x800C3D50; // type:func
mSDI_StartDataInit = 0x800C3DA8; // type:func
func_800C3E30_jp = 0x800C3E30; // type:func
-func_800C3F70_jp = 0x800C3F70; // type:func
+mString_Load_StringFromRom = 0x800C3F70; // type:func
func_800C4084_jp = 0x800C4084; // type:func
func_800C40F8_jp = 0x800C40F8; // type:func
func_800C4168_jp = 0x800C4168; // type:func
@@ -3463,7 +3463,7 @@ lbRTC_IsOverTime = 0x800D52C0; // type:func
lbRTC_IsJustAtRTC = 0x800D53A4; // type:func
lbRTC_IsOverRTC = 0x800D53DC; // type:func
lbRTC_IsOverWeekRTC = 0x800D5414; // type:func
-func_800D5480_jp = 0x800D5480; // type:func
+lbRTC_IntervalTime = 0x800D5480; // type:func
lbRTC_GetIntervalDays = 0x800D54DC; // type:func
lbRTC_Add_YY = 0x800D56B8; // type:func
lbRTC_Add_MM = 0x800D56CC; // type:func
@@ -4724,7 +4724,7 @@ D_8010AEE0_jp = 0x8010AEE0; //
D_8010AEF4_jp = 0x8010AEF4; //
D_8010AF00_jp = 0x8010AF00; // type:s16
D_8010AF30_jp = 0x8010AF30; // type:s16
-D_8010AF58_jp = 0x8010AF58; // type:u8
+npc_looks_table = 0x8010AF58; // type:u8
D_8010B034_jp = 0x8010B034; //
D_8010B074_jp = 0x8010B074; //
D_8010B078_jp = 0x8010B078; //
@@ -4751,7 +4751,7 @@ D_8010B4B0_jp = 0x8010B4B0; // type:u16
D_8010B4FC_jp = 0x8010B4FC; // type:u16
D_8010B500_jp = 0x8010B500; //
D_8010B504_jp = 0x8010B504; // type:s16
-D_8010B510_jp = 0x8010B510; // type:u16
+l_sp_actor_name = 0x8010B510; //
D_8010B810_jp = 0x8010B810; //
D_8010B818_jp = 0x8010B818; //
D_8010B81C_jp = 0x8010B81C; //
@@ -6097,29 +6097,24 @@ B_80142BA0_jp = 0x80142BA0; //
B_80142BBE_jp = 0x80142BBE; //
B_80142BC0_jp = 0x80142BC0; // type:u8
B_80142BE0_jp = 0x80142BE0; //
-B_80142C00_jp = 0x80142C00; //
-B_80142CF0_jp = 0x80142CF0; //
-B_80142D08_jp = 0x80142D08; //
-B_80142E38_jp = 0x80142E38; //
-B_80142E58_jp = 0x80142E58; //
-B_80142E78_jp = 0x80142E78; //
-B_80142E80_jp = 0x80142E80; //
-B_80142E98_jp = 0x80142E98; //
-B_80142EB8_jp = 0x80142EB8; //
-B_80142ED8_jp = 0x80142ED8; // type:s8
-B_80142EDA_jp = 0x80142EDA; // type:u8
-B_80142EDB_jp = 0x80142EDB; // type:s8
-B_80142EDC_jp = 0x80142EDC; // type:u16
-B_80142EDE_jp = 0x80142EDE; // type:s16
-B_80142EE0_jp = 0x80142EE0; // type:s8
-B_80142F50_jp = 0x80142F50; //
-B_80142F58_jp = 0x80142F58; //
-B_80142F60_jp = 0x80142F60; //
-B_80142F68_jp = 0x80142F68; //
-B_80142F70_jp = 0x80142F70; //
-B_80142F80_jp = 0x80142F80; //
-B_80143028_jp = 0x80143028; //
-B_80143388_jp = 0x80143388; //
+fake_table = 0x80142C00; //
+Handbillz_tmp_super = 0x80142CF0; //
+reserved = 0x80142D08; //
+Handbillz_tmp_ps = 0x80142E38; //
+candidate_table = 0x80142E58; //
+npc_def_list = 0x80142E78; //
+Remail_tmp_super = 0x80142E80; //
+Remail_tmp_ps = 0x80142E98; //
+fg_flag = 0x80142EB8; //
+l_npc_talk_info = 0x80142ED8; // type:s8
+Event_animal_name = 0x80142F50; //
+Birthday_animal_name = 0x80142F58; //
+Goodby_animal_name = 0x80142F60; //
+load_name = 0x80142F68; //
+l_mnpc_goodby_mail = 0x80142F70; //
+l_npc_mail = 0x80142F80; //
+fakeTable = 0x80143028; //
+l_mnpc_remove_in_animal = 0x80143388; //
B_801438B0_jp = 0x801438B0; //
B_801438B8_jp = 0x801438B8; //
B_801438BC_jp = 0x801438BC; //
diff --git a/src/boot/libc64/malloc.c b/src/boot/libc64/malloc.c
index c079153..826ada5 100644
--- a/src/boot/libc64/malloc.c
+++ b/src/boot/libc64/malloc.c
@@ -19,7 +19,7 @@ void free(void* ptr) {
__osFree(&malloc_arena, ptr);
}
-void* calloc(s32 num, size_t size) {
+void* calloc(size_t num, size_t size) {
void* ptr;
u32 n = num * size;
diff --git a/src/code/lb_rtc.c b/src/code/lb_rtc.c
index 8935435..d9e6453 100644
--- a/src/code/lb_rtc.c
+++ b/src/code/lb_rtc.c
@@ -283,7 +283,7 @@ s32 lbRTC_IsOverWeekRTC(const lbRTC_time_c* t0, lbRTC_weekday_t week) {
lbRTC_IsOverRTC(&t1);
}
-void func_800D5480_jp(lbRTC_time_c* t0, lbRTC_time_c* t1) {
+s32 lbRTC_IntervalTime(lbRTC_time_c* t0, lbRTC_time_c* t1) {
lbRTC_time_c t2;
lbRTC_time_c t3;
diff --git a/src/code/m_field_info.c b/src/code/m_field_info.c
index 09cf4c8..ec2873c 100644
--- a/src/code/m_field_info.c
+++ b/src/code/m_field_info.c
@@ -7,7 +7,7 @@
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_80087C40_jp.s")
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_80087C64_jp.s")
+#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/mFI_GetBlockTopP.s")
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/mFI_GetFieldId.s")
@@ -51,7 +51,7 @@
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/mFI_Wpos2BlockNum.s")
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_80088780_jp.s")
+#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/mFI_Wpos2BkandUtNuminBlock.s")
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008883C_jp.s")
@@ -65,7 +65,7 @@
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_80088B3C_jp.s")
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_80088BC0_jp.s")
+#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/mFI_UtNum2PosXZInBk.s")
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_80088BFC_jp.s")
@@ -119,7 +119,7 @@
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_800894D0_jp.s")
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_80089538_jp.s")
+#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/mFI_GetBkNum2ColTop.s")
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_800895B8_jp.s")
@@ -157,7 +157,7 @@
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008A000_jp.s")
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008A33C_jp.s")
+#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/mFI_BkNumtoUtFGTop.s")
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008A3BC_jp.s")
@@ -237,11 +237,11 @@
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008BBF0_jp.s")
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008BC64_jp.s")
+#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/mFI_SetMoveActorBitData_ON.s")
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008BCFC_jp.s")
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008BD98_jp.s")
+#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/mFI_MyMoveActorBitData_ON.s")
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008BDCC_jp.s")
@@ -261,7 +261,7 @@
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008C130_jp.s")
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008C1E0_jp.s")
+#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/mFI_GetDepositP.s")
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008C344_jp.s")
@@ -275,7 +275,7 @@
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008C458_jp.s")
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008C478_jp.s")
+#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/mFI_BlockDepositOFF.s")
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_8008C498_jp.s")
@@ -361,7 +361,7 @@ s32 mFI_GetWaveUtinBlock(s32* arg0, s32* arg1, s32 arg2, s32 arg3) {
arg0[0] = 0;
arg1[0] = 0;
- temp_v0 = var_s1 = func_80089538_jp(arg2, arg3);
+ temp_v0 = var_s1 = mFI_GetBkNum2ColTop(arg2, arg3);
if (temp_v0 != NULL) {
diff --git a/src/code/m_mail.c b/src/code/m_mail.c
index d816fe2..d967753 100644
--- a/src/code/m_mail.c
+++ b/src/code/m_mail.c
@@ -2,7 +2,7 @@
#include "m_common_data.h"
#include "m_lib.h"
#include "m_npc.h"
-#include "6B8A70.h"
+#include "m_land.h"
#include "unknown_structs.h"
#include "macros.h"
@@ -50,21 +50,21 @@ void mMl_strcpy_back(char* dst, const char* src, s32 size) {
}
}
-void mMl_clear_mail_header(Mail* mail) {
- mPr_ClearPersonalID(&mail->unk_00.unk_00);
- mail->unk_00.unk_10 = 0xFF;
- mPr_ClearPersonalID(&mail->unk_12.unk_00);
- mail->unk_12.unk_10 = 0xFF;
+void mMl_clear_mail_header(Mail_c* mail) {
+ mPr_ClearPersonalID(&mail->header.recipient.personalID);
+ mail->header.recipient.type = 0xFF;
+ mPr_ClearPersonalID(&mail->header.sender.personalID);
+ mail->header.sender.type = 0xFF;
}
-void mMl_clear_mail(Mail* mail) {
- bzero(mail, sizeof(Mail));
+void mMl_clear_mail(Mail_c* mail) {
+ bzero(mail, sizeof(Mail_c));
mMl_clear_mail_header(mail);
- mem_clear((u8*)&mail->unk_2A, sizeof(mMl_unk_2A), 0x20);
- mail->unk_26 = 0xFF;
+ mem_clear(mail->content.header, MAIL_HEADER_LEN + MAIL_BODY_LEN + MAIL_FOOTER_LEN, 0x20);
+ mail->content.font = 0xFF;
}
-void mMl_clear_mail_box(Mail mail[], s32 arg1) {
+void mMl_clear_mail_box(Mail_c mail[], s32 arg1) {
while (arg1 != 0) {
arg1--;
mMl_clear_mail(mail);
@@ -72,47 +72,47 @@ void mMl_clear_mail_box(Mail mail[], s32 arg1) {
}
}
-s32 mMl_check_not_used_mail(Mail* mail) {
+s32 mMl_check_not_used_mail(Mail_c* mail) {
s32 ret = 0;
- if (mail->unk_26 == 0xFF) {
+ if (mail->content.font == 0xFF) {
ret = 1;
}
return ret;
}
void mMl_copy_header_name(mMl_unk_00* arg0, mMl_unk_00* arg1) {
- arg0->unk_10 = arg1->unk_10;
- mPr_CopyPersonalID(&arg0->unk_00, &arg1->unk_00);
+ arg0->type = arg1->type;
+ mPr_CopyPersonalID(&arg0->personalID, &arg1->personalID);
}
-void mMl_set_from_name(Mail* arg0, Mail* arg1) {
- mMl_copy_header_name(&arg0->unk_12, &arg1->unk_00);
+void mMl_set_from_name(Mail_c* arg0, Mail_c* arg1) {
+ mMl_copy_header_name(&arg0->header.sender, &arg1->header.recipient);
}
-void mMl_set_to_name(Mail* arg0, Mail* arg1) {
- mMl_copy_header_name(&arg0->unk_00, &arg1->unk_00);
+void mMl_set_to_name(Mail_c* arg0, Mail_c* arg1) {
+ mMl_copy_header_name(&arg0->header.recipient, &arg1->header.recipient);
}
-void mMl_set_to_plname(Mail* arg0, Mail* arg1) {
- mPr_CopyPersonalID(&arg0->unk_00.unk_00, &arg1->unk_00.unk_00);
- arg0->unk_00.unk_10 = 0;
+void mMl_set_to_plname(Mail_c* arg0, Mail_c* arg1) {
+ mPr_CopyPersonalID(&arg0->header.recipient.personalID, &arg1->header.recipient.personalID);
+ arg0->header.recipient.type = 0;
}
-void mMl_set_playername(Mail* mail, PersonalID* arg1) {
- mPr_CopyPersonalID(&mail->unk_12.unk_00, arg1);
- mail->unk_12.unk_10 = 0;
+void mMl_set_playername(Mail_c* mail, PersonalID_c* arg1) {
+ mPr_CopyPersonalID(&mail->header.sender.personalID, arg1);
+ mail->header.sender.type = 0;
}
-void mMl_init_mail(Mail* mail, PersonalID* arg1) {
+void mMl_init_mail(Mail_c* mail, PersonalID_c* arg1) {
mMl_clear_mail(mail);
mMl_set_playername(mail, arg1);
- mail->unk_26 = 1;
- mail->unk_28 = 0;
- mail->unk_29 = 0;
+ mail->content.font = 1;
+ mail->content.mailType = 0;
+ mail->content.paperType = 0;
}
-s32 mMl_chk_mail_free_space(Mail mail[], s32 arg1) {
+s32 mMl_chk_mail_free_space(Mail_c mail[], s32 arg1) {
s32 i;
for (i = 0; i < arg1; i++) {
@@ -124,7 +124,7 @@ s32 mMl_chk_mail_free_space(Mail mail[], s32 arg1) {
return -1;
}
-s32 mMl_use_mail_space(Mail mail[], s32 arg1, PersonalID* arg2) {
+s32 mMl_use_mail_space(Mail_c mail[], s32 arg1, PersonalID_c* arg2) {
s32 index = mMl_chk_mail_free_space(mail, arg1);
if (index != -1) {
@@ -133,7 +133,7 @@ s32 mMl_use_mail_space(Mail mail[], s32 arg1, PersonalID* arg2) {
return index;
}
-s32 mMl_count_use_mail_space(Mail mail[], s32 arg1) {
+s32 mMl_count_use_mail_space(Mail_c mail[], s32 arg1) {
s32 i;
s32 ret = 0;
@@ -146,8 +146,8 @@ s32 mMl_count_use_mail_space(Mail mail[], s32 arg1) {
return ret;
}
-void mMl_copy_mail(Mail* dst, Mail* src) {
- mem_copy((u8*)dst, (u8*)src, sizeof(Mail));
+void mMl_copy_mail(Mail_c* dst, Mail_c* src) {
+ mem_copy((u8*)dst, (u8*)src, sizeof(Mail_c));
}
void mMl_clear_mail_header_common(MailHeaderCommon* arg0) {
@@ -161,40 +161,40 @@ void mMl_copy_mail_header_common(MailHeaderCommon* arg0, MailHeaderCommon* arg1)
mem_copy((u8*)arg0, (u8*)arg1, sizeof(MailHeaderCommon));
}
-void mMl_set_mail_name_npcinfo(mMl_unk_00* arg0, mMl_get_npcinfo_from_mail_name_arg0* arg1) {
- PlayerName sp20;
+void mMl_set_mail_name_npcinfo(mMl_unk_00* arg0, AnmPersonalID_c* arg1) {
+ char name[PLAYER_NAME_LEN];
- arg0->unk_10 = 1;
- mNpc_GetNpcWorldNameAnm(&sp20, arg1);
- mPr_CopyPlayerName(&arg0->unk_00.unk_0, &sp20);
- arg0->unk_00.unk_E = arg1->unk_2;
- mLd_CopyLandName(&arg0->unk_00.unk_6, &arg1->unk_4);
- arg0->unk_00.unk_C = ((arg1->unk_0 & 0xFF) << 8) | (arg1->unk_A & 0xFF);
+ arg0->type = 1;
+ mNpc_GetNpcWorldNameAnm(name, arg1);
+ mPr_CopyPlayerName(arg0->personalID.playerName, name);
+ arg0->personalID.landId = arg1->landId;
+ mLd_CopyLandName(arg0->personalID.landName, arg1->landName);
+ arg0->personalID.playerId = ((arg1->npcId & 0xFF) << 8) | (arg1->nameId & 0xFF);
}
-s32 mMl_get_npcinfo_from_mail_name(mMl_get_npcinfo_from_mail_name_arg0* arg0, mMl_unk_00* arg1) {
+s32 mMl_get_npcinfo_from_mail_name(AnmPersonalID_c* arg0, mMl_unk_00* arg1) {
s32 var_v1 = 0;
- if (arg1->unk_10 == 1) {
- arg0->unk_0 = (((arg1->unk_00.unk_C & 0xFF00) >> 8) | 0xE000);
- arg0->unk_2 = arg1->unk_00.unk_E;
- mLd_CopyLandName(&arg0->unk_4, &arg1->unk_00.unk_6);
- arg0->unk_A = arg1->unk_00.unk_C & 0xFFFF;
- arg0->unk_B = mNpc_GetLooks(arg0->unk_0);
+ if (arg1->type == 1) {
+ arg0->npcId = (((arg1->personalID.playerId & 0xFF00) >> 8) | 0xE000);
+ arg0->landId = arg1->personalID.landId;
+ mLd_CopyLandName(arg0->landName, arg1->personalID.landName);
+ arg0->nameId = arg1->personalID.playerId & 0xFFFF;
+ arg0->looks = mNpc_GetLooks(arg0->npcId);
var_v1 = 1;
}
return var_v1;
}
-s32 mMl_hunt_for_send_address(Mail* mail) {
+s32 mMl_hunt_for_send_address(Mail_c* mail) {
s32 i;
- if (mail->unk_00.unk_10 != 0) {
+ if (mail->header.recipient.type != 0) {
return -1;
}
for (i = 0; i < ARRAY_COUNT(common_data.homes); i++) {
- if (mPr_CheckCmpPersonalID(&common_data.homes[i].unk_000, &mail->unk_00.unk_00) == 1) {
+ if (mPr_CheckCmpPersonalID(&common_data.homes[i].ownerID, &mail->header.recipient.personalID) == 1) {
return i;
}
}
@@ -212,8 +212,8 @@ s32 mMl_check_send_mail(struct_func_8085CE18_jp_arg4* arg0) {
}
}
-s32 mMl_check_set_present_myself(Mail* mail) {
- switch (mail->unk_26) {
+s32 mMl_check_set_present_myself(Mail_c* mail) {
+ switch (mail->content.font) {
case 1:
case 3:
case 4:
diff --git a/src/code/m_npc.c b/src/code/m_npc.c
new file mode 100644
index 0000000..281e63b
--- /dev/null
+++ b/src/code/m_npc.c
@@ -0,0 +1,3984 @@
+#include "m_npc.h"
+#include "macros.h"
+#include "m_lib.h"
+#include "m_land.h"
+#include "m_time.h"
+#include "m_field_info.h"
+#include "m_mail_check.h"
+#include "6E30B0.h"
+#include "6E7AD0.h"
+#include "m_handbill.h"
+#include "z_std_dma.h"
+#include "6DA460.h"
+#include "m_house.h"
+#include "m_malloc.h"
+#include "segment_symbols.h"
+#include "m_item_name.h"
+#include "m_name_table.h"
+#include "m_police_box.h"
+#include "6A5B00.h"
+#include "6A83A0.h"
+
+SpecialNpcData l_sp_actor_name[] = {
+ { 0xD008, NPC_SEX_MALE, 0x0205, 2 }, { 0xD01E, NPC_SEX_MALE, 0x0205, 2 }, { 0xD03A, NPC_SEX_MALE, 0x0205, 2 },
+ { 0xD03B, NPC_SEX_MALE, 0x0205, 2 }, { 0xD03C, NPC_SEX_MALE, 0x0205, 2 }, { 0xD009, NPC_SEX_MALE, 0x0205, 2 },
+ { 0xD00A, NPC_SEX_MALE, 0x0205, 2 }, { 0xD00B, NPC_SEX_MALE, 0x0205, 2 }, { 0xD014, NPC_SEX_MALE, 0x0205, 2 },
+ { 0xD019, NPC_SEX_MALE, 0x0205, 2 }, { 0xD015, NPC_SEX_MALE, 0x0205, 2 }, { 0xD01A, NPC_SEX_MALE, 0x0205, 2 },
+ { 0xD016, NPC_SEX_MALE, 0x0205, 2 }, { 0xD01B, NPC_SEX_MALE, 0x0205, 2 }, { 0xD017, NPC_SEX_MALE, 0x0205, 2 },
+ { 0xD01C, NPC_SEX_MALE, 0x0205, 2 }, { 0xD001, NPC_SEX_MALE, 0x0206, 2 }, { 0xD013, NPC_SEX_MALE, 0x0206, 2 },
+ { 0xD02C, NPC_SEX_MALE, 0x0206, 2 }, { 0xD039, NPC_SEX_MALE, 0x0206, 2 }, { 0xD00C, NPC_SEX_FEMALE, 0x0207, 2 },
+ { 0xD03D, NPC_SEX_FEMALE, 0x0207, 2 }, { 0xD006, NPC_SEX_MALE, 0x0208, 2 }, { 0xD000, NPC_SEX_MALE, 0x0209, 3 },
+ { 0xD00F, NPC_SEX_MALE, 0x020A, 2 }, { 0xD002, NPC_SEX_MALE, 0x020B, 2 }, { 0xD007, NPC_SEX_FEMALE, 0x020C, 8 },
+ { 0xD003, NPC_SEX_FEMALE, 0x020D, 4 }, { 0xD012, NPC_SEX_FEMALE, 0x020E, 4 }, { 0xD011, NPC_SEX_MALE, 0x020F, 3 },
+ { 0xD00D, NPC_SEX_MALE, 0x0210, 2 }, { 0xD010, NPC_SEX_MALE, 0x0210, 3 }, { 0xD04E, NPC_SEX_MALE, 0x0210, 2 },
+ { 0xD00E, NPC_SEX_MALE, 0x0211, 2 }, { 0xD025, NPC_SEX_MALE, 0x0212, 3 }, { 0xA004, NPC_SEX_OTHER, 0x0213, 2 },
+ { 0xA005, NPC_SEX_OTHER, 0x0213, 2 }, { 0xA006, NPC_SEX_OTHER, 0x0213, 2 }, { 0xA007, NPC_SEX_OTHER, 0x0213, 2 },
+ { 0xD018, NPC_SEX_OTHER, 0x0214, 2 }, { 0xD05D, NPC_SEX_OTHER, 0x0214, 2 }, { 0xD066, NPC_SEX_OTHER, 0x0214, 2 },
+ { 0xD004, NPC_SEX_MALE, 0x0215, 2 }, { 0xD005, NPC_SEX_MALE, 0x0215, 2 }, { 0xD01D, NPC_SEX_MALE, 0x0216, 2 },
+ { 0xD026, NPC_SEX_MALE, 0x0217, 2 }, { 0xD037, NPC_SEX_MALE, 0x0218, 2 }, { 0xD03E, NPC_SEX_MALE, 0x04E0, 2 },
+ { 0xD065, NPC_SEX_MALE, 0x04E0, 2 }, { 0xD068, NPC_SEX_MALE, 0x04E0, 2 }, { 0xD069, NPC_SEX_MALE, 0x04E0, 2 },
+ { 0xD06B, NPC_SEX_MALE, 0x04E0, 2 }, { 0xD064, NPC_SEX_MALE, 0x04E1, 2 }, { 0x800D, NPC_SEX_MALE, 0x04E2, 2 },
+ { 0x800E, NPC_SEX_MALE, 0x04E2, 2 }, { 0xA008, NPC_SEX_MALE, 0x04E2, 2 }, { 0xA009, NPC_SEX_MALE, 0x04E2, 2 },
+ { 0xA00A, NPC_SEX_MALE, 0x04E2, 2 }, { 0xA00B, NPC_SEX_MALE, 0x04E2, 2 }, { 0xA00C, NPC_SEX_MALE, 0x04E2, 2 },
+ { 0xA00D, NPC_SEX_MALE, 0x04E2, 2 }, { 0xA00E, NPC_SEX_MALE, 0x04E2, 2 }, { 0xA00F, NPC_SEX_MALE, 0x04E2, 2 },
+ { 0xA010, NPC_SEX_MALE, 0x04E2, 2 },
+};
+char l_no_name_npc_name[ANIMAL_NAME_LEN] = { 0xD4, 0x8E, 0xA6, 0x90, 0x85, 0x42 };
+char l_no_ending_npc_ending[ANIMAL_CATCHPHRASE_LEN] = { 0xD3, 0xAF, 0x9D, 0x20 };
+
+s32 fake_table[60];
+u8 Handbillz_tmp_super[MAIL_HEADER2_LEN];
+Anmhome_c reserved[60];
+u8 Handbillz_tmp_ps[MAIL_FOOTER2_LEN];
+u8 candidate_table[27];
+static u32 bssPad;
+NpcDefaultData npc_def_list;
+u8 Remail_tmp_super[MAIL_HEADER2_LEN];
+u8 Remail_tmp_ps[MAIL_FOOTER2_LEN];
+u16 fg_flag[UT_Z_NUM];
+NpcTalkInfo l_npc_talk_info[ANIMAL_NUM_MAX];
+char Event_animal_name[ANIMAL_NAME_LEN];
+char Birthday_animal_name[ANIMAL_NAME_LEN];
+char Goodby_animal_name[ANIMAL_NAME_LEN];
+char load_name[ANIMAL_NAME_LEN];
+AnmGoodbyeMail l_mnpc_goodby_mail;
+Mail_c l_npc_mail;
+s32 fakeTable[NPC_NUM];
+Animal_c l_mnpc_remove_in_animal;
+
+void mNpc_MakeRandTable(s32* table, s32 count, s32 swapNum) {
+ s32 b;
+ s32 i;
+
+ for (i = 0; i < count; i++) {
+ table[i] = i;
+ }
+
+ while (swapNum--) {
+ s32 temp;
+
+ i = RANDOM(count);
+ b = RANDOM(count);
+ temp = table[i];
+
+ table[i] = table[b];
+ table[b] = temp;
+ }
+}
+
+void mNpc_ClearBufSpace1(u8* buf, s32 size) {
+ mem_clear(buf, size, 0x20);
+}
+
+void mNpc_AddNowNpcMax(u8* npcMax) {
+ if (npcMax[0] < ANIMAL_NUM_MAX) {
+ npcMax[0]++;
+ }
+}
+
+void mNpc_SubNowNpcMax(u8* npcMax) {
+ if (npcMax[0] > ANIMAL_NUM_MIN) {
+ npcMax[0]--;
+ }
+}
+
+void mNpc_ClearAnimalPersonalID(AnmPersonalID_c* pid) {
+ pid->npcId = 0;
+ pid->nameId = 0xFF;
+ pid->landId = 0xFFFF;
+ pid->looks = 6;
+ mNPS_reset_schedule_area(pid);
+ mLd_ClearLandName(pid->landName);
+}
+
+s32 mNpc_CheckFreeAnimalPersonalID(AnmPersonalID_c* pid) {
+ s32 res = FALSE;
+
+ if ((pid->npcId == 0 && pid->nameId == 0xFF) || (ACTOR_FGNAME_GET_F000(pid->npcId) != FGNAME_F000_E)) {
+ res = TRUE;
+ }
+
+ return res;
+}
+
+void mNpc_CopyAnimalPersonalID(AnmPersonalID_c* dst, AnmPersonalID_c* src) {
+ if ((src != NULL) && (ACTOR_FGNAME_GET_F000(src->npcId) == FGNAME_F000_E)) {
+ dst->npcId = src->npcId;
+ dst->nameId = src->nameId;
+ dst->landId = src->landId;
+ dst->looks = src->looks;
+ mLd_CopyLandName(dst->landName, src->landName);
+ }
+}
+
+s32 mNpc_CheckCmpAnimalPersonalID(AnmPersonalID_c* id0, AnmPersonalID_c* id1) {
+ s32 res = FALSE;
+
+ if ((id0 != NULL) && (id1 != NULL) && (id0->npcId == id1->npcId) && (id0->nameId == id1->nameId) &&
+ (id0->landId == id1->landId)) {
+ if (mLd_CheckCmpLandName(id0->landName, id1->landName) == TRUE) {
+ res = TRUE;
+ }
+ }
+ return res;
+}
+
+s32 mNpc_GetAnimalNum() {
+ Animal_c* animal = common_data.animals;
+ s32 num = 0;
+ s32 i;
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (mNpc_CheckFreeAnimalPersonalID(&animal->id) == FALSE) {
+ num++;
+ }
+
+ animal++;
+ }
+
+ return num;
+}
+
+s32 mNpc_CheckRemoveExp(Animal_c* animal) {
+ s32 res = (animal->removeInfo >> 13) & 7;
+
+ return res;
+}
+
+s32 mNpc_GetRemoveTime(Animal_c* animal) {
+ s32 res = animal->removeInfo & 0x1FFF;
+
+ return res;
+}
+
+void mNpc_AddRemoveTime(Animal_c* animal) {
+ if ((animal->removeInfo & 0x1FFF) < 0x1FFF) {
+ animal->removeInfo++;
+ }
+}
+
+void mNpc_SetRemoveExp(Animal_c* animal, u16 removeExp) {
+ animal->removeInfo = ((((animal->removeInfo >> 13) & 7) >> 13) | removeExp) << 13;
+}
+
+void mNpc_SetParentName(Animal_c* animal, PersonalID_c* parentId) {
+ if ((parentId != NULL && mPr_NullCheckPersonalID(parentId) == FALSE) &&
+ (mPr_NullCheckPlayerName(animal->parentName) == TRUE)) {
+ mPr_CopyPlayerName(animal->parentName, parentId->playerName);
+ }
+}
+
+void mNpc_SetParentNameAllAnimal() {
+ Animal_c* animal = common_data.animals;
+ PrivateInfo* priv = common_data.privateInfo;
+ s32 i;
+
+ if (priv != NULL) {
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ mNpc_SetParentName(animal, &priv->playerId);
+ animal++;
+ }
+ }
+}
+
+void mNpc_ClearAnimalMail(Anmplmail_c* mail) {
+ mail->font = 0xFF;
+ mail->paperType = 0;
+ mail->present = 0;
+ mem_clear(mail->body, sizeof(mail->body), 0x20);
+ mail->date.year = mTM_rtcTime_ymd_clear_code.year;
+ mail->date.month = mTM_rtcTime_ymd_clear_code.month;
+ mail->date.day = mTM_rtcTime_ymd_clear_code.day;
+}
+
+void mNpc_CopyAnimalMail(Anmplmail_c* dst, Anmplmail_c* src) {
+ mem_copy((u8*)dst, (u8*)src, sizeof(Anmplmail_c));
+}
+
+void mNpc_ClearAnimalMemory(Anmmem_c* memory, s32 num) {
+ for (; num != 0; num--) {
+ if (memory != NULL) {
+ mPr_ClearPersonalID(&memory->memoryPlayerId);
+ lbRTC_TimeCopy(&memory->lastSpeakTime, &mTM_rtcTime_clear_code);
+ mLd_ClearLandName(memory->land.name);
+ memory->land.id = 0;
+ memory->savedTownTune = 0;
+ memory->friendship = 0;
+ memory->letterInfo.exists = FALSE;
+ memory->letterInfo.cond = 0;
+ memory->letterInfo.sendReply = FALSE;
+ mNpc_ClearAnimalMail(&memory->letter);
+ }
+
+ memory++;
+ }
+}
+
+void mNpc_CopyAnimalMemory(Anmmem_c* dst, Anmmem_c* src) {
+ mem_copy((u8*)dst, (u8*)src, sizeof(Anmmem_c));
+}
+
+void mNpc_AddFriendship(Anmmem_c* memory, s32 amount) {
+ s32 friendship = memory->friendship + amount;
+
+ if (memory == NULL) {
+ return;
+ }
+
+ if (friendship > 127) {
+ memory->friendship = 127;
+ } else if (friendship < 0) {
+ memory->friendship = 0;
+ } else {
+ memory->friendship = friendship;
+ }
+}
+
+s32 mNpc_CheckFreeAnimalMemory(Anmmem_c* memory) {
+ s32 res = FALSE;
+
+ if (mPr_NullCheckPersonalID(&memory->memoryPlayerId) == TRUE) {
+ res = TRUE;
+ }
+
+ return res;
+}
+
+void mNpc_RenewalAnimalMemory() {
+ PrivateInfo* priv;
+ Animal_c* animal = common_data.animals;
+ Anmmem_c* memory;
+ s32 i;
+ s32 j;
+ s32 k;
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ memory = animal->memories;
+
+ for (j = 0; j < ANIMAL_MEMORY_NUM; j++) {
+ if (mNpc_CheckFreeAnimalMemory(memory) == FALSE &&
+ mLd_CheckThisLand(memory->memoryPlayerId.landName, memory->memoryPlayerId.landId) == TRUE) {
+ priv = common_data.saveFilePrivateInfo;
+
+ for (k = 0; k < PLAYER_NUM; k++) {
+ if (mPr_NullCheckPersonalID(&priv->playerId) == FALSE &&
+ mPr_CheckCmpPersonalID(&priv->playerId, &memory->memoryPlayerId) == TRUE) {
+ break;
+ }
+
+ priv++;
+ }
+
+ if (k == PLAYER_NUM) {
+ mNpc_ClearAnimalMemory(memory, 1);
+ }
+ }
+ memory++;
+ }
+ animal++;
+ }
+}
+
+s32 mNpc_GetOldAnimalMemoryIdx(Anmmem_c* memory, s32 num) {
+ lbRTC_time_c oldest;
+ s32 res;
+ s32 i;
+
+ lbRTC_TimeCopy(&oldest, &mTM_rtcTime_clear_code);
+ res = 0;
+
+ for (i = 0; i < num; i++) {
+ if (lbRTC_IsOverTime(&oldest, &memory->lastSpeakTime) == lbRTC_LESS) {
+ res = i;
+ lbRTC_TimeCopy(&oldest, &memory->lastSpeakTime);
+ }
+
+ memory++;
+ }
+
+ return res;
+}
+
+s32 mNpc_GetFreeAnimalMemoryIdx(Anmmem_c* memory, s32 num) {
+ s32 res = -1;
+ s32 i;
+
+ for (i = 0; i < num; i++) {
+ if (mNpc_CheckFreeAnimalMemory(memory) == TRUE) {
+ res = i;
+ break;
+ }
+
+ memory++;
+ }
+
+ return res;
+}
+
+s32 mNpc_ForceGetFreeAnimalMemoryIdx(Anmmem_c* memory, s32 num) {
+ Anmmem_c* chosenMem = NULL;
+ s32 freeId = mNpc_GetFreeAnimalMemoryIdx(memory, num);
+ s32 i;
+
+ if (freeId == -1) {
+ for (i = 0; i < num; i++) {
+ if (mLd_CheckThisLand(memory->memoryPlayerId.landName, memory->memoryPlayerId.landId) == 0) {
+ if (chosenMem != NULL) {
+ if (chosenMem->letterInfo.exists == memory->letterInfo.exists) {
+ if (memory->friendship < chosenMem->friendship) {
+ chosenMem = memory;
+ freeId = i;
+ } else if ((chosenMem->friendship == memory->friendship) &&
+ (lbRTC_IsOverTime(&chosenMem->lastSpeakTime, &memory->lastSpeakTime) == -1)) {
+ chosenMem = memory;
+ freeId = i;
+ }
+ } else if (memory->letterInfo.exists == FALSE) {
+ chosenMem = memory;
+ freeId = i;
+ }
+ } else {
+ chosenMem = memory;
+ freeId = i;
+ }
+ }
+ memory++;
+ }
+ } else {
+ chosenMem = &memory[freeId];
+ }
+ mNpc_ClearAnimalMemory(chosenMem, 1);
+ return freeId;
+}
+
+void mNpc_SetAnimalMemory_NotSetDay(PersonalID_c* pid, Anmmem_c* memory) {
+ if (memory != NULL) {
+ mNpc_ClearAnimalMemory(memory, 1);
+ mPr_CopyPersonalID(&memory->memoryPlayerId, pid);
+ memory->friendship = 1;
+ }
+}
+
+void mNpc_SetAnimalMemory(PersonalID_c* pid, Anmmem_c* memory) {
+ lbRTC_time_c* rtcTime = &common_data.time.rtcTime;
+
+ if (memory != NULL) {
+ mNpc_SetAnimalMemory_NotSetDay(pid, memory);
+ lbRTC_TimeCopy(&memory->lastSpeakTime, rtcTime);
+ }
+}
+
+s32 mNpc_GetAnimalMemoryIdx(PersonalID_c* pid, Anmmem_c* memory, s32 num) {
+ s32 res = -1;
+ s32 i;
+
+ for (i = 0; i < num; i++) {
+ if (mPr_CheckCmpPersonalID(&memory->memoryPlayerId, pid) == TRUE) {
+ res = i;
+ break;
+ }
+ memory++;
+ }
+
+ return res;
+}
+
+void mNpc_SetAnimalLastTalk(Animal_c* animal) {
+ PrivateInfo* priv;
+ Anmmem_c* memory = NULL;
+ s32 memoryIdx;
+
+ if ((&common_data.privateInfo->playerId != NULL) && (animal != NULL)) {
+ priv = common_data.privateInfo;
+ memoryIdx = mNpc_GetAnimalMemoryIdx(&priv->playerId, animal->memories, ANIMAL_MEMORY_NUM);
+
+ if (memoryIdx != -1) {
+ memory = &animal->memories[memoryIdx];
+ } else {
+ memoryIdx = mNpc_ForceGetFreeAnimalMemoryIdx(animal->memories, ANIMAL_MEMORY_NUM);
+
+ if (memoryIdx != -1) {
+ memory = &animal->memories[memoryIdx];
+ mNpc_SetAnimalMemory(&priv->playerId, memory);
+ }
+ }
+
+ if (memory != NULL) {
+ lbRTC_TimeCopy(&memory->lastSpeakTime, &common_data.time.rtcTime);
+ mLd_CopyLandName(memory->land.name, common_data.landInfo.name);
+ memory->land.id = common_data.landInfo.id;
+ memory->savedTownTune = common_data.melody;
+ }
+ }
+}
+
+void mNpc_SetAnimalPersonalID2Memory(AnmPersonalID_c* anmId) {
+ PrivateInfo* priv = priv = common_data.privateInfo;
+ Animal_c* animal;
+ s32 id;
+
+ if (priv != NULL) {
+ id = mNpc_SearchAnimalPersonalID(anmId);
+
+ if (id != -1) {
+ animal = &common_data.animals[id];
+ id = mNpc_GetAnimalMemoryIdx(&priv->playerId, animal->memories, ANIMAL_MEMORY_NUM);
+
+ if (id == -1) {
+ id = mNpc_ForceGetFreeAnimalMemoryIdx(animal->memories, ANIMAL_MEMORY_NUM);
+
+ if (id != -1) {
+ mNpc_SetAnimalMemory_NotSetDay(&priv->playerId, animal->memories + id);
+ }
+ }
+ }
+ }
+}
+
+s32 mNpc_GetHighestFriendshipIdx(Anmmem_c* memory, s32 num) {
+ s8 max = 0;
+ s32 res = -1;
+ s32 i;
+
+ for (i = 0; i < num; i++) {
+ if (mNpc_CheckFreeAnimalMemory(memory) == FALSE) {
+ if (max <= memory->friendship) {
+ max = memory->friendship;
+ res = i;
+ }
+ }
+ memory++;
+ }
+
+ return res;
+}
+
+s32 mNpc_SelectBestFriend(Anmmem_c** bestFriendMem, Anmmem_c* memory, s8* bestFriendFriendShip) {
+ s32 res = FALSE;
+ Anmmem_c* bestFriend;
+
+ if (memory->friendship > bestFriendFriendShip[0]) {
+ bestFriendFriendShip[0] = memory->friendship;
+ bestFriendMem[0] = memory;
+ res = TRUE;
+ } else if (memory->friendship == bestFriendFriendShip[0]) {
+ bestFriend = bestFriendMem[0];
+
+ if (bestFriend != NULL) {
+ if (bestFriend->letterInfo.exists == memory->letterInfo.exists) {
+ if (lbRTC_IsOverTime(&bestFriend->lastSpeakTime, &memory->lastSpeakTime) == lbRTC_LESS) {
+ bestFriendMem[0] = memory;
+ res = TRUE;
+ }
+ } else if (memory->letterInfo.exists == TRUE) {
+ bestFriendMem[0] = memory;
+ res = TRUE;
+ }
+ } else {
+ bestFriendMem[0] = memory;
+ res = TRUE;
+ }
+ }
+
+ return res;
+}
+
+s32 mNpc_GetAnimalMemoryBestFriend(Anmmem_c* memory, s32 num) {
+
+ Anmmem_c* memoryP = memory;
+ Anmmem_c* best_friend = NULL;
+ s8 best_friendship = 0;
+ UNUSED s8 pad;
+ s32 res = -1;
+ s32 i;
+
+ for (i = 0; i < num; i++) {
+ if ((mNpc_CheckFreeAnimalMemory(memory) == FALSE) &&
+ (mNpc_SelectBestFriend(&best_friend, memory, &best_friendship) == TRUE)) {
+ res = i;
+ }
+
+ memory++;
+ }
+
+ if (res != -1 && (memoryP[res].friendship < 80)) {
+ res = -1;
+ }
+
+ return res;
+}
+
+s32 mNpc_GetAnimalMemoryFriend_Land_Sex(Anmmem_c* memory, s32 num, s32 sex) {
+ Anmmem_c* bestFriend = NULL;
+ s8 bestFriendship = 0;
+ s32 id;
+ s32 res = -1;
+ s32 i;
+
+ for (i = 0; i < num; i++) {
+ if (mNpc_CheckFreeAnimalMemory(memory) == FALSE) {
+ id = mPr_GetPrivateIdx(&memory->memoryPlayerId);
+
+ if (id != -1 && common_data.saveFilePrivateInfo[id].gender == sex &&
+ mNpc_SelectBestFriend(&bestFriend, memory, &bestFriendship) == TRUE) {
+ res = i;
+ }
+ }
+
+ memory++;
+ }
+
+ return res;
+}
+
+s32 mNpc_GetAnimalMemoryNum(Anmmem_c* memory, s32 count) {
+ s32 num = 0;
+ s32 i;
+
+ for (i = 0; i < count; i++) {
+ if (mNpc_CheckFreeAnimalMemory(memory) == FALSE) {
+ num++;
+ }
+
+ memory++;
+ }
+
+ return num;
+}
+
+s32 mNpc_GetAnimalMemoryLetterNum(Anmmem_c* memory, s32 count) {
+ s32 num = 0;
+ s32 i;
+
+ for (i = 0; i < count; i++) {
+ if (mNpc_CheckFreeAnimalMemory(memory) == FALSE && memory->letterInfo.exists == TRUE) {
+ num++;
+ }
+
+ memory++;
+ }
+
+ return num;
+}
+
+s32 mNpc_GetAnimalMemoryLandKindNum(Anmmem_c* memory, s32 count) {
+ Anmmem_c* memory2;
+ u8 bitfield = 0xFF;
+ s32 num = 0;
+ s32 i;
+ s32 j;
+
+ for (i = 0; i < count; i++) {
+ if (mNpc_CheckFreeAnimalMemory(memory) == FALSE) {
+ if (((bitfield >> i) & 1) == 1) {
+ j = i + 1;
+ memory2 = memory + 1;
+
+ for (j = i + 1; j < count; j++) {
+ if (((bitfield >> j) & 1) == 1) {
+ if (mLd_CheckCmpLand(memory->land.name, memory->land.id, memory2->land.name,
+ memory2->land.id) == TRUE) {
+ bitfield &= ~(1 << j);
+ }
+ }
+
+ memory2++;
+ }
+ }
+ num++;
+ } else {
+ bitfield &= ~(1 << i);
+ }
+
+ memory++;
+ }
+ return num;
+}
+
+void mNpc_ClearAnimalInfo(Animal_c* animal) {
+ Anmhome_c* home = &animal->homeInfo;
+ bzero(animal, sizeof(Animal_c));
+ mNpc_ClearAnimalPersonalID(&animal->id);
+ mNpc_ClearAnimalMemory(animal->memories, ANIMAL_MEMORY_NUM);
+ animal->cloth = 0;
+ home->typeUnused = 0;
+ home->blockX = 0xFF;
+ home->blockZ = 0xFF;
+ home->utX = 0xFF;
+ home->utZ = 0xFF;
+ mNpc_ClearBufSpace1((u8*)animal->catchphrase, ANIMAL_CATCHPHRASE_LEN);
+ mQst_ClearContest(&animal->contestQuest);
+ mLd_ClearLandName(animal->previousLandName);
+ animal->previousLandId = 0;
+ animal->removeInfo = 0;
+ animal->isHome = TRUE;
+ mPr_ClearPlayerName(animal->parentName);
+}
+
+void mNpc_ClearAnyAnimalInfo(Animal_c* animals, s32 count) {
+ s32 i;
+
+ for (i = 0; i < count; i++) {
+ mNpc_ClearAnimalInfo(animals);
+ animals++;
+ }
+}
+
+s32 mNpc_CheckFreeAnimalInfo(Animal_c* animal) {
+ s32 res = FALSE;
+
+ if ((animal->homeInfo.blockX == 0xFF) && (animal->homeInfo.blockZ == 0xFF) &&
+ (ACTOR_FGNAME_GET_F000(animal->id.npcId) != FGNAME_F000_E)) {
+ res = TRUE;
+ }
+ return res;
+}
+
+s32 mNpc_GetFreeAnimalInfo(Animal_c* animal, s32 count) {
+ s32 res = -1;
+ s32 i;
+
+ for (i = 0; i < count; i++) {
+ if (mNpc_CheckFreeAnimalInfo(animal) == TRUE) {
+ res = i;
+ break;
+ }
+ animal++;
+ }
+
+ return res;
+}
+
+s32 mNpc_UseFreeAnimalInfo(Animal_c* animal, s32 count) {
+ s32 idx = mNpc_GetFreeAnimalInfo(animal, count);
+
+ if (idx != -1) {
+ mNpc_ClearAnimalInfo(&animal[idx]);
+ }
+ return idx;
+}
+
+void mNpc_CopyAnimalInfo(Animal_c* dst, Animal_c* src) {
+ mem_copy((u8*)dst, (u8*)src, sizeof(Animal_c));
+}
+
+s32 mNpc_SearchAnimalinfo(Animal_c* animal, u16 npcName, s32 count) {
+ s32 idx;
+
+ animal = &animal[count - 1];
+ idx = count - 1;
+
+ while (idx >= 0) {
+ if (animal->id.npcId == npcName) {
+ return idx;
+ }
+ idx--;
+ animal--;
+ }
+
+ return -1;
+}
+
+Animal_c* mNpc_GetAnimalInfoP(u16 id) {
+ UNUSED s32 pad;
+ Animal_c* animal = NULL;
+ s32 idx = mNpc_SearchAnimalinfo(common_data.animals, id, ANIMAL_NUM_MAX);
+
+ if (idx != -1) {
+ animal = common_data.animals + idx;
+ }
+
+ return animal;
+}
+
+s32 mNpc_SearchAnimalPersonalID(AnmPersonalID_c* id) {
+ Animal_c* animal = common_data.animals;
+ s32 res = -1;
+ s32 i;
+
+ if (id != NULL && !mNpc_CheckFreeAnimalPersonalID(id)) {
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (mNpc_CheckCmpAnimalPersonalID(id, &animal->id) == TRUE) {
+ res = i;
+ break;
+ }
+ animal++;
+ }
+ }
+
+ return res;
+}
+
+AnmPersonalID_c* mNpc_GetOtherAnimalPersonalIDOtherBlock(AnmPersonalID_c* pids, s32 count, s32 blockX, s32 blockY,
+ s32 flag) {
+ UNUSED s32 pad;
+ AnmPersonalID_c* otherId;
+ u8 npcMax;
+ UNUSED s32 pad1;
+ s32 ids;
+ u16 bitfield;
+ s32 j;
+ s32 i;
+ UNUSED s32 pad2[2];
+ s32 valid;
+ Animal_c* animal = common_data.animals;
+ s32 tempHome;
+ s32 homesInBlock;
+
+ otherId = NULL;
+ homesInBlock = 0;
+ ids = count;
+ npcMax = common_data.nowNpcMax;
+ bitfield = 0xFFFF;
+
+ if ((blockX == 0xFF) || (blockY == 0xFF)) {
+ flag = 0;
+ }
+
+ if ((pids == NULL) && (count != 0)) {
+ count = 0;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (mNpc_CheckFreeAnimalPersonalID(&pids[i]) == TRUE) {
+ ids--;
+ bitfield &= ~(1 << i);
+ }
+ }
+
+ if (flag == 1) {
+ for (j = 0; j < ANIMAL_NUM_MAX; j++) {
+ if (blockX == animal->homeInfo.blockX) {
+ if (blockY == animal->homeInfo.blockZ) {
+ homesInBlock++;
+
+ for (i = 0; i < count; i++) {
+ if ((((bitfield >> i) & 1) == TRUE) &&
+ (mNpc_CheckCmpAnimalPersonalID(&animal->id, &pids[i]) == TRUE)) {
+ ids--;
+ bitfield &= ~(1 << i);
+ break;
+ }
+ }
+ }
+ }
+ animal++;
+ }
+ }
+ if (((ids + homesInBlock) < npcMax) && (count < ANIMAL_NUM_MAX)) {
+ animal = common_data.animals;
+ tempHome = fqrand() * ((npcMax - ids) - homesInBlock);
+
+ for (j = 0; j < ANIMAL_NUM_MAX; j++) {
+ homesInBlock = 0;
+ valid = 1;
+
+ if (mNpc_CheckFreeAnimalPersonalID(&animal->id) == 0) {
+ for (i = 0; i < count; i++) {
+ if ((((bitfield >> i) & 1) == 1) &&
+ (mNpc_CheckCmpAnimalPersonalID(&animal->id, &pids[i]) == FALSE)) {
+ homesInBlock++;
+ }
+ if (homesInBlock) {}
+ }
+
+ if (homesInBlock != ids) {
+ valid = 0;
+ } else if ((flag == 1) && (blockX == animal->homeInfo.blockX) && (blockY == animal->homeInfo.blockZ)) {
+ if (tempHome > 0) {
+ tempHome--;
+ }
+ valid = 0;
+ }
+
+ if (valid == 1) {
+ if (tempHome == 0) {
+ otherId = &animal->id;
+ break;
+ }
+ tempHome--;
+ }
+ }
+ animal++;
+ }
+ j = 0;
+ }
+
+ return otherId;
+}
+
+AnmPersonalID_c* mNpc_GetOtherAnimalPersonalID(AnmPersonalID_c* pids, s32 count) {
+ return mNpc_GetOtherAnimalPersonalIDOtherBlock(pids, count, 0, 0, FALSE);
+}
+
+void mNpc_SetAnimalThisLand(Animal_c* animal, s32 count) {
+ LandInfo* landInfo = &common_data.landInfo;
+
+ for (; count != 0; count--) {
+ if (!mNpc_CheckFreeAnimalPersonalID(&animal->id)) {
+ animal->id.landId = landInfo->id;
+ mLd_CopyLandName(animal->id.landName, landInfo->name);
+ }
+
+ animal++;
+ }
+}
+
+s32 mNpc_GetSameLooksNum(u8 looks) {
+ Animal_c* animal = common_data.animals;
+ s32 i;
+ s32 num = 0;
+
+ if (looks < NPC_LOOKS_NUM) {
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (looks == animal->id.looks) {
+ num++;
+ }
+
+ animal++;
+ }
+ }
+
+ return num;
+}
+
+s32 mNpc_CheckNpcExistBlock(s32 idx, s32 checkBx, s32 checkBz) {
+ UNUSED s32 pad;
+ s32 bx;
+ s32 bz;
+ s32 res = FALSE;
+
+ if (idx >= 0 && idx < (ANIMAL_NUM_MAX)) {
+ if ((mFI_Wpos2BlockNum(&bx, &bz, common_data.npclist[idx].position) == TRUE) && (bx == checkBx) &&
+ (bz == checkBz)) {
+ res = TRUE;
+ }
+ }
+
+ return res;
+}
+
+void mNpc_Mail2AnimalMail(Anmplmail_c* animalMail, Mail_c* mail) {
+ mem_copy((u8*)animalMail->body, (u8*)mail->content.body, MAIL_BODY_LEN);
+ mem_copy((u8*)animalMail->header, (u8*)mail->content.header, MAIL_HEADER_LEN);
+ mem_copy((u8*)animalMail->footer, (u8*)mail->content.footer, MAIL_FOOTER_LEN);
+
+ animalMail->headerBackStart = mail->content.headerBackStart;
+ animalMail->font = mail->content.font;
+ animalMail->present = mail->present;
+ animalMail->paperType = mail->content.paperType;
+}
+
+void mNpc_AnimalMail2Mail(Mail_c* mail, Anmplmail_c* animal_mail, PersonalID_c* pid, AnmPersonalID_c* anmId) {
+ mem_copy((u8*)mail->content.body, (u8*)animal_mail->body, MAIL_BODY_LEN);
+ mem_copy((u8*)mail->content.header, (u8*)animal_mail->header, MAIL_HEADER_LEN);
+ mem_copy((u8*)mail->content.footer, (u8*)animal_mail->footer, MAIL_FOOTER_LEN);
+
+ mail->content.headerBackStart = animal_mail->headerBackStart;
+ mail->content.font = animal_mail->font;
+ mail->present = animal_mail->present;
+ mail->content.paperType = animal_mail->paperType;
+
+ if (pid != NULL) {
+ mPr_CopyPersonalID(&mail->header.sender.personalID, pid);
+ mail->header.sender.type = MAIL_NAME_TYPE_PLAYER;
+ }
+
+ if (anmId != NULL) {
+ mMl_set_mail_name_npcinfo(&mail->header.recipient, anmId);
+ }
+}
+
+s32 mNpc_CheckMailChar(u8 c) {
+ if ((c == 0x21) || (c == 0x22) || (c == 0x5F) || (c == 0x90) || (c == 0x5C) || ((c >= 0x25) && (c <= 0x40)) ||
+ ((c >= 0x7F) && (c <= 0x85))) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+s32 mNpc_CheckNormalMail_sub(s32* num, u8* body) {
+ UNUSED s32 pad[2];
+ s32 consecutiveChars = 0;
+ u8 lastChar = 0x20;
+ s32 runningLen = 1;
+ s32 contentLen = 0;
+ s32 i;
+
+ *num = 0;
+
+ for (i = 0; i < MAIL_BODY_LEN; i++) {
+ if (*body != 0x20) {
+ runningLen++;
+ if (lastChar == *body) {
+ if (runningLen >= 3) {
+ if (mNpc_CheckMailChar(*body) == TRUE) {
+ if (runningLen >= 8) {
+ consecutiveChars = TRUE;
+ break;
+ }
+ } else {
+ consecutiveChars = TRUE;
+ break;
+ }
+ }
+ } else {
+ runningLen = 0;
+ lastChar = *body;
+ }
+ (*num)++;
+ }
+ body++;
+ contentLen++;
+ }
+
+ for (i = contentLen; i < MAIL_BODY_LEN; i++) {
+ if (*body != 0x20) {
+ (*num)++;
+ }
+ body++;
+ }
+
+ return consecutiveChars;
+}
+
+u8 mNpc_CheckNormalMail_length(s32* len, u8* body) {
+ s32 hitRate;
+ s32 hitChars;
+ s32 running;
+
+ u8 rank = 2;
+
+ hitRate = mMC_get_mail_hit_rate(&hitChars, body, NULL);
+ running = mNpc_CheckNormalMail_sub(len, body);
+
+ if (hitChars < 3) {
+ if (len[0] < 5) {
+ rank = 0;
+ } else if (running == TRUE) {
+ rank = 0;
+ }
+ } else if (hitRate >= 30) {
+ rank = 1;
+ } else if (running == TRUE) {
+ rank = 0;
+ }
+
+ return rank;
+}
+
+u8 mNpc_CheckNormalMail(u8* body) {
+ s32 length;
+
+ return mNpc_CheckNormalMail_length(&length, body);
+}
+
+s32 mNpc_SetMailCondThisLand(Anmmem_c* memory, u8* body) {
+ u8 cond;
+
+ memory->letter.date.year = common_data.time.rtcTime.year;
+ memory->letter.date.month = common_data.time.rtcTime.month;
+ memory->letter.date.day = common_data.time.rtcTime.day;
+
+ cond = mNpc_CheckNormalMail(body);
+
+ if (cond < 2) {
+ memory->letterInfo.cond = cond;
+ memory->letterInfo.sendReply = TRUE;
+ }
+
+ return cond;
+}
+
+s32 mNpc_SetMailCondOtherLand(Animal_c* animal, u8* body) {
+ Anmremail* remail;
+ u8 cond = mNpc_CheckNormalMail(body);
+
+ if (cond < 2) {
+ remail = &common_data.privateInfo->remail;
+
+ remail->date.year = common_data.time.rtcTime.year;
+ remail->date.month = common_data.time.rtcTime.month;
+ remail->date.day = common_data.time.rtcTime.day;
+ remail->flags.cond = cond;
+ remail->flags.looks = animal->id.looks;
+
+ mNpc_GetNpcWorldNameAnm(remail->name, &animal->id);
+ mLd_CopyLandName(remail->landName, mLd_GetLandName());
+ }
+
+ return cond;
+}
+
+s32 mNpc_SetRemailCond(Animal_c* animal, Anmmem_c* memory, u8* body) {
+ s32 res;
+
+ if (mLd_PlayerManKindCheck() == FALSE) {
+ res = mNpc_SetMailCondThisLand(memory, body);
+ } else {
+ res = mNpc_SetMailCondOtherLand(animal, body);
+ }
+
+ return res;
+}
+
+s32 mNpc_SendMailtoNpc(Mail_c* mail) {
+ AnmPersonalID_c anmId;
+ s32 res = FALSE;
+ Animal_c* animal;
+ s32 fakeTemp;
+ s32 anmIdx;
+ Anmmem_c* memory;
+ s32 cond;
+ s32 memoryIdx;
+ Anmplmail_c* plmail;
+ Animal_c* anm;
+
+ if (mMl_get_npcinfo_from_mail_name(&anmId, &mail->header.recipient) == TRUE) {
+ anm = common_data.animals;
+ anmIdx = mNpc_SearchAnimalPersonalID(&anmId);
+
+ if (anmIdx != -1) {
+ animal = &anm[anmIdx];
+ memoryIdx = mNpc_GetAnimalMemoryIdx(&mail->header.sender.personalID, animal->memories, ANIMAL_MEMORY_NUM);
+
+ if (memoryIdx == -1) {
+ memoryIdx = mNpc_ForceGetFreeAnimalMemoryIdx(animal->memories, ANIMAL_MEMORY_NUM);
+
+ if (memoryIdx >= 0) {
+ mPr_CopyPersonalID(&animal->memories[memoryIdx].memoryPlayerId, &mail->header.sender.personalID);
+ }
+ }
+
+ memory = &animal->memories[memoryIdx];
+ plmail = &memory->letter;
+ memory->letterInfo.exists = TRUE;
+ mNpc_ClearAnimalMail(plmail);
+ mNpc_Mail2AnimalMail(plmail, mail);
+ cond = mNpc_SetRemailCond(animal, memory, mail->content.body);
+ fakeTemp = 0xFF;
+ if (mEv_CheckFirstJob() == TRUE) {
+ QuestErrand* firstJob = mQst_GetFirstJobData();
+
+ if ((firstJob->base.questKind == 6 || firstJob->base.questKind == 10) && firstJob->base.progress != 0) {
+ firstJob->base.progress = 3;
+ memory->letterInfo.sendReply = FALSE;
+ }
+ } else {
+ s32 friendship;
+
+ if (mLd_PlayerManKindCheck() == FALSE) {
+ if (mQst_GetOccuredContestIdx(6) == anmIdx) {
+ mQst_SetReceiveLetter(&animal->contestQuest, &mail->header.sender.personalID,
+ mail->content.body, mail->present);
+ memory->letterInfo.sendReply = FALSE;
+ }
+ }
+
+ /* FAKE! */
+ friendship = (3 & fakeTemp) & fakeTemp & fakeTemp & fakeTemp & fakeTemp & fakeTemp & fakeTemp &
+ fakeTemp & fakeTemp & fakeTemp;
+
+ if (cond == 0) {
+ friendship -= 5;
+ }
+
+ if (mail->present != 0) {
+ friendship += 3;
+ }
+
+ mNpc_AddFriendship(memory, friendship);
+ }
+
+ res = TRUE;
+ }
+ }
+
+ return res;
+}
+
+void mNpc_ClearRemail(Anmremail* remail) {
+ remail->date = mTM_rtcTime_ymd_clear_code;
+ mPr_ClearPlayerName(remail->name);
+ mLd_ClearLandName(remail->landName);
+ remail->flags.cond = 0;
+ remail->flags.looks = 0x7F;
+}
+
+void mNpc_GetRemailPresent(u16* present) {
+ static s32 category_table[2] = { 0, 2 };
+
+ mSP_SelectRandomItem_New(NULL, present, 1, NULL, 0, category_table[RANDOM(4) & 1], 8);
+}
+
+s32 mNpc_GetHandbillz(Mail_c* mail, s32 superNum, s32 mailANum, s32 mailBNum, s32 mailCNum, s32 psNum) {
+ HandbillzInfo handbill;
+ s32 res;
+
+ handbill.superBuf = Handbillz_tmp_super;
+ handbill.superBufSize = MAIL_HEADER2_LEN;
+ handbill.mailBuf = mail->content.body;
+ handbill.mailBufSize = MAIL_BODY_LEN;
+ handbill.psBuf = Handbillz_tmp_ps;
+ handbill.psBufSize = MAIL_FOOTER2_LEN;
+ handbill.superNo = superNum;
+ handbill.mailANo = mailANum;
+ handbill.mailBNo = mailBNum;
+ handbill.mailCNo = mailCNum;
+ handbill.psNo = psNum;
+
+ res = mHandbillz_load(&handbill);
+ if (res == TRUE) {
+ mail->content.headerBackStart = handbill.headerBackStart;
+ mem_copy((u8*)mail->content.header, Handbillz_tmp_super, MAIL_HEADER_LEN);
+ mem_copy((u8*)mail->content.footer, Handbillz_tmp_ps, MAIL_FOOTER_LEN);
+ }
+
+ return res;
+}
+
+void mNpc_SetRemailFreeString(PersonalID_c* pid, AnmPersonalID_c* anmId, Anmremail* remail) {
+ static s32 base_str_no[11] = {
+ 0x314, // food
+ 0x334, // sports
+ 0x2F4, // hobby games
+ 0x219, // fish
+ 0x1E5, // insects
+ 0x354, // food tastes (sweet, spicy, ...)
+ 0x374, // feelings
+ 0x394, // music genres
+ 0x3D4, // food satisfaction feelings (delicious, stuffed, satisfying, ...)
+ 0x3F4, // "good" descriptors (brilliant, splendid, ...)
+ 0x3B4 // "bad" descriptors (unimpressive, awful, ...)
+ };
+
+ s32 i;
+ char freeStr[10];
+
+ mHandbill_Set_free_str(0, pid->playerName, PLAYER_NAME_LEN);
+
+ if (remail == NULL) {
+ mNpc_GetNpcWorldNameAnm(freeStr, anmId);
+ mHandbill_Set_free_str(1, freeStr, ANIMAL_NAME_LEN);
+
+ mNpc_GetNpcWorldNameAnm(freeStr, mNpc_GetOtherAnimalPersonalID(anmId, 1));
+ mHandbill_Set_free_str(2, freeStr, ANIMAL_NAME_LEN);
+ } else {
+ mHandbill_Set_free_str(1, remail->name, ANIMAL_NAME_LEN); // foreign npc name
+ mNpc_GetNpcWorldNameAnm(freeStr, mNpc_GetOtherAnimalPersonalID(NULL, 0));
+ mHandbill_Set_free_str(2, freeStr, ANIMAL_NAME_LEN); // random player town npc name
+ mHandbill_Set_free_str(14, remail->landName, LAND_NAME_SIZE); // foreign town name
+ mHandbill_Set_free_str(15, mLd_GetLandName(), LAND_NAME_SIZE); // player town name
+ }
+
+ for (i = 0; i < ARRAY_COUNT(base_str_no); i++) {
+
+ mString_Load_StringFromRom(freeStr, ARRAY_COUNT(freeStr), base_str_no[i] + RANDOM(32.0f));
+ mHandbill_Set_free_str(3 + i, freeStr, ARRAY_COUNT(freeStr));
+ }
+}
+
+void mNpc_GetRemailGoodData(Mail_c* mail, PersonalID_c* pid, AnmPersonalID_c* anmId, Anmremail* remail, u8 foreign) {
+ static s32 start_no[NPC_LOOKS_NUM] = { 0x020, 0x040, 0x000, 0x060, 0x080, 0x0A0 };
+
+ static s32 ohter_start_no[NPC_LOOKS_NUM] = { 0x0E0, 0x100, 0x0C0, 0x120, 0x140, 0x160 };
+
+ static s32* start_no_table[2] = { start_no, ohter_start_no };
+
+ s32* msgTbl;
+ s32 givePresent;
+ u16 present = 0;
+ s32 looks;
+ s32 msgNo;
+
+ if (remail == NULL) {
+ looks = anmId->looks;
+ } else {
+ looks = remail->flags.looks;
+ }
+
+ msgTbl = start_no_table[foreign];
+
+ givePresent = RANDOM(4) & 1;
+
+ if (givePresent == 0) {
+ mNpc_GetRemailPresent(&present);
+ }
+
+ mNpc_SetRemailFreeString(pid, anmId, remail);
+ msgNo = msgTbl[looks];
+ mNpc_GetHandbillz(mail, msgNo + RANDOM(32), msgNo + RANDOM(32), msgNo + RANDOM(16) + givePresent * 16,
+ msgNo + RANDOM(32), msgNo + RANDOM(32));
+ mail->present = present;
+}
+
+void mNpc_GetRemailWrongData(Mail_c* mail, PersonalID_c* pid, AnmPersonalID_c* anmId, Anmremail* remail, u8 foreign) {
+ static s32 mail_no[2] = { 0xC5, 0xD8 };
+ s32 msgNo;
+ s32 looks;
+ s32 headerBackStart;
+
+ if (remail == NULL) {
+ looks = anmId->looks;
+ } else {
+ looks = remail->flags.looks;
+ }
+
+ mNpc_SetRemailFreeString(pid, anmId, remail);
+ msgNo = mail_no[foreign] + looks * 3;
+ msgNo += RANDOM2(3.0f);
+ mHandbill_Load_HandbillFromRom(Remail_tmp_super, &headerBackStart, Remail_tmp_ps, mail->content.body, msgNo);
+ mail->content.headerBackStart = headerBackStart;
+ mem_copy((u8*)mail->content.header, Remail_tmp_super, MAIL_HEADER_LEN);
+ mem_copy((u8*)mail->content.footer, Remail_tmp_ps, MAIL_FOOTER_LEN);
+ mail->present = 0;
+}
+
+typedef void (*NpcGetRemailProc)(Mail_c*, PersonalID_c*, AnmPersonalID_c*, Anmremail*, u8);
+
+void mNpc_GetRemailData(Mail_c* mail, PersonalID_c* pid, AnmPersonalID_c* anmId, Anmremail* remail, s32 cond,
+ u8 foreign) {
+ static NpcGetRemailProc get_remail[] = {
+ &mNpc_GetRemailWrongData,
+ &mNpc_GetRemailGoodData,
+ };
+
+ u16 paper;
+
+ get_remail[cond](mail, pid, anmId, remail, foreign);
+ mail->content.font = 0;
+ mail->content.mailType = 0;
+ mPr_CopyPersonalID(&mail->header.recipient.personalID, pid);
+ mail->header.recipient.type = MAIL_NAME_TYPE_PLAYER;
+
+ if (remail == NULL) {
+ mMl_set_mail_name_npcinfo(&mail->header.sender, anmId);
+ } else {
+ mPr_CopyPlayerName(mail->header.sender.personalID.playerName, remail->name);
+ mLd_CopyLandName(mail->header.sender.personalID.landName, remail->landName);
+ mail->header.sender.type = MAIL_NAME_TYPE_NPC;
+ }
+
+ mSP_SelectRandomItem_New(NULL, &paper, 1, NULL, 0, 1, 8);
+ mail->content.paperType = (paper - 0x2000) & 0xFFFF;
+}
+
+s32 mNpc_SendRemailPostOffice(PersonalID_c* pid, AnmPersonalID_c* anmId, Anmremail* remail, s32 cond, u8 foreign) {
+ Mail_c* mail = &l_npc_mail;
+ s32 res = FALSE;
+
+ if (mPO_get_keep_mail_sum() < 5) {
+ mNpc_GetRemailData(mail, pid, anmId, remail, cond, foreign);
+ res = mPO_receipt_proc(mail, 0);
+ }
+
+ return res;
+}
+
+s32 mNpc_CheckLetterTime(lbRTC_ymd_t* letterDate, lbRTC_time_c* rtcTime) {
+ s32 res = FALSE;
+
+ if (letterDate->day != 0xFF &&
+ (letterDate->year != rtcTime->year || letterDate->month != rtcTime->month || letterDate->day != rtcTime->day)) {
+ res = TRUE;
+ }
+
+ return res;
+}
+
+void mNpc_Remail() {
+ Animal_c* animal = common_data.animals;
+ Anmremail* remail;
+ PrivateInfo* priv = common_data.privateInfo;
+ Anmmem_c* memory;
+ lbRTC_time_c* rtcTime = &common_data.time.rtcTime;
+
+ if (mPr_NullCheckPersonalID(&priv->playerId) == FALSE && mLd_PlayerManKindCheck() == FALSE) {
+ s32 i;
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (mNpc_CheckFreeAnimalPersonalID(&animal->id) == FALSE) {
+ s32 memIdx = mNpc_GetAnimalMemoryIdx(&priv->playerId, animal->memories, ANIMAL_MEMORY_NUM);
+
+ if (memIdx != -1) {
+ memory = animal->memories + memIdx;
+
+ if (memory->letterInfo.sendReply && mNpc_CheckLetterTime(&memory->letter.date, rtcTime) == TRUE) {
+ if (mNpc_SendRemailPostOffice(&priv->playerId, &animal->id, NULL, memory->letterInfo.cond,
+ FALSE) != TRUE) {
+ break;
+ }
+
+ memory->letterInfo.sendReply = FALSE;
+ }
+ }
+ }
+
+ animal++;
+ }
+
+ remail = &priv->remail;
+ if (remail->flags.looks != 0x7F &&
+ mNpc_SendRemailPostOffice(&priv->playerId, &animal->id, remail, remail->flags.cond, TRUE) == TRUE) {
+ mNpc_ClearRemail(remail);
+ }
+ }
+}
+
+u8 mNpc_GetPaperType() {
+ u16 paper;
+
+ mSP_SelectRandomItem_New(NULL, &paper, 1, NULL, 0, 1, 8);
+ return (paper - 0x2000) & 0xFFFF;
+}
+
+void mNpc_LoadMailDataCommon2(Mail_c* mail, PersonalID_c* pid, AnmPersonalID_c* amnId, u16 present, u8 paperType,
+ s32 mailNo) {
+ u8 super[MAIL_HEADER2_LEN];
+ u8 ps[MAIL_FOOTER2_LEN];
+ s32 headerBackStart;
+
+ mMl_clear_mail(mail);
+ mHandbill_Load_HandbillFromRom2(super, MAIL_HEADER2_LEN, &headerBackStart, ps, MAIL_HEADER2_LEN, mail->content.body,
+ mailNo);
+ mem_copy(mail->content.header, super, MAIL_HEADER_LEN);
+ mem_copy(mail->content.footer, ps, MAIL_FOOTER_LEN);
+ mail->content.headerBackStart = headerBackStart;
+ mail->content.font = 0;
+ mail->content.mailType = 0;
+ mPr_CopyPersonalID(&mail->header.recipient.personalID, pid);
+ mail->header.recipient.type = MAIL_NAME_TYPE_PLAYER;
+ mMl_set_mail_name_npcinfo(&mail->header.sender, amnId);
+ mail->present = present;
+ mail->content.paperType = paperType;
+}
+
+void mNpc_GetEventPresent(u16* present, s32 type) {
+ static s32 priority_table[3] = {
+ 5,
+ 2,
+ 0,
+ };
+
+ static s32 category_table[3] = {
+ 0,
+ 0,
+ 2,
+ };
+
+ mSP_SelectRandomItem_New(NULL, present, 1, NULL, 0, category_table[type], priority_table[type]);
+}
+
+void mNpc_GetEventMail(Mail_c* mail, PersonalID_c* pid, AnmPersonalID_c* anmId, s32 type, s32 looks) {
+ u16 present;
+ UNUSED s32 pad;
+
+ mHandbill_Set_free_str(0, pid->playerName, PLAYER_NAME_LEN);
+ mNpc_GetNpcWorldNameAnm(Event_animal_name, anmId);
+ mHandbill_Set_free_str(6, Event_animal_name, ANIMAL_NAME_LEN);
+ mNpc_GetEventPresent(&present, type);
+ mNpc_LoadMailDataCommon2(mail, pid, anmId, present, mNpc_GetPaperType(), 0x60 + (looks * 3) + type);
+}
+
+s32 mNpc_SendEventPresentMail(PersonalID_c* pid, s32 playerNo, AnmPersonalID_c* anmId, s32 type) {
+ UNUSED s32 pad;
+ mHm_hs_c* home;
+ UNUSED s32 pad2;
+ s32 freeIdx;
+ s32 looks;
+ s32 res;
+
+ looks = anmId->looks;
+ res = FALSE;
+
+ home = &common_data.homes[mHS_get_arrange_idx(playerNo)];
+
+ if (mPr_CheckCmpPersonalID(pid, &home->ownerID) == TRUE) {
+
+ freeIdx = mMl_chk_mail_free_space(home->mailbox, HOME_MAILBOX_SIZE);
+
+ if (freeIdx != -1) {
+ mNpc_GetEventMail(&l_npc_mail, pid, anmId, type, looks);
+ mMl_copy_mail(home->mailbox + freeIdx, &l_npc_mail);
+ res = TRUE;
+ } else if (mPO_get_keep_mail_sum() < 5) {
+ mNpc_GetEventMail(&l_npc_mail, pid, anmId, type, looks);
+ res = mPO_receipt_proc(&l_npc_mail, 0);
+ }
+ }
+
+ return res;
+}
+
+void mNpc_SendEventPresentMailSex(s32* selected, u8* type, Animal_c* animal, NpcSex sex) {
+ s32 bestFriendIdx = mNpc_GetAnimalMemoryBestFriend(animal->memories, ANIMAL_MEMORY_NUM);
+ s32 otherSexBestFriend = mNpc_GetAnimalMemoryFriend_Land_Sex(animal->memories, ANIMAL_MEMORY_NUM, (~sex) & 1);
+
+ if (bestFriendIdx != -1 && otherSexBestFriend == bestFriendIdx) {
+ selected[0] = otherSexBestFriend;
+ type[0] = 0;
+ } else if (otherSexBestFriend != -1) {
+ selected[0] = otherSexBestFriend;
+
+ if (animal->memories[otherSexBestFriend].friendship >= 80) {
+ type[0] = 1;
+ } else {
+ type[0] = 2;
+ }
+ }
+}
+
+s32 mNpc_SendEventPresentMail_common(NpcSex sexType) {
+ static NpcSex sex[] = { NPC_SEX_FEMALE, NPC_SEX_MALE };
+
+ Animal_c* animal = common_data.animals;
+ PersonalID_c* pid;
+ s32 otherSexBestFriends[ANIMAL_NUM_MAX];
+ u8 types[ANIMAL_NUM_MAX];
+ s32 playerNo;
+ s32 sent = 0;
+ u8 bitfield = 0xF;
+ s32 i;
+ s32 j;
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ otherSexBestFriends[i] = -1;
+
+ if (mNpc_CheckFreeAnimalPersonalID(&animal->id) == FALSE) {
+ if (mNpc_GetAnimalSex(animal) == sex[sexType]) {
+ mNpc_SendEventPresentMailSex(&otherSexBestFriends[i], &types[i], animal, sex[sexType]);
+ }
+ }
+
+ animal++;
+ }
+
+ for (i = 0; i < 3; i++) {
+ animal = common_data.animals;
+
+ for (j = 0; j < ANIMAL_NUM_MAX; j++) {
+ if (otherSexBestFriends[j] >= 0 && types[j] == i) {
+ pid = &animal->memories[otherSexBestFriends[j]].memoryPlayerId;
+ playerNo = mPr_GetPrivateIdx(pid);
+
+ if (((bitfield >> playerNo) & 1) == 1) {
+ if (mNpc_SendEventPresentMail(pid, playerNo, &animal->id, i) == TRUE) {
+ otherSexBestFriends[j] = -1;
+ sent++;
+ } else {
+ bitfield &= ~(1 << playerNo); // remove player from bitfield because they can't receive letters
+ }
+ }
+ }
+
+ if (bitfield == 0) {
+ return sent; // all players cannot receive any further mail
+ }
+
+ animal++;
+ }
+ }
+ return sent;
+}
+
+void mNpc_GetBirthdayPresent(u16* present) {
+ static u8 category_table[5] = { 0, 0, 2, 2, 0xFF };
+
+ s32 selected = category_table[RANDOM(ARRAY_COUNT(category_table))];
+
+ if (selected == 0xFF) {
+ mSP_RandomUmbSelect(present, 1);
+ } else {
+ mSP_SelectRandomItem_New(NULL, present, 1, NULL, 0, selected, 2);
+ }
+}
+
+void mNpc_GetBirthdayCard(Mail_c* mail, PersonalID_c* pid, AnmPersonalID_c* anmId) {
+ char itemName[10];
+ s32 mailNo = 0xEA + anmId->looks * 3 + RANDOM(3);
+ u16 present;
+
+ mHandbill_Set_free_str(0, pid->playerName, PLAYER_NAME_LEN);
+ mNpc_GetNpcWorldNameAnm(Birthday_animal_name, anmId);
+ mHandbill_Set_free_str(1, Birthday_animal_name, ANIMAL_NAME_LEN);
+ mNpc_GetBirthdayPresent(&present);
+ mIN_copy_name_str(itemName, present);
+ mHandbill_Set_free_str(2, itemName, 10);
+ mNpc_LoadMailDataCommon2(mail, pid, anmId, present, mNpc_GetPaperType(), mailNo);
+}
+
+s32 mNpc_SendBirthdayCard(PersonalID_c* pid, s32 playerNo, AnmPersonalID_c* anm_id) {
+ UNUSED s32 pad;
+ mHm_hs_c* home;
+ UNUSED s32 pad2;
+ s32 freeIdx;
+ s32 res = FALSE;
+
+ home = &common_data.homes[mHS_get_arrange_idx(playerNo)];
+
+ if (mPr_NullCheckPersonalID(pid) == FALSE && mPr_CheckCmpPersonalID(pid, &home->ownerID) == TRUE) {
+ freeIdx = mMl_chk_mail_free_space(home->mailbox, 10);
+
+ if (freeIdx != -1) {
+ mNpc_GetBirthdayCard(&l_npc_mail, pid, anm_id);
+ mMl_copy_mail(home->mailbox + freeIdx, &l_npc_mail);
+ res = TRUE;
+ } else if (mPO_get_keep_mail_sum() < 5) {
+ mNpc_GetBirthdayCard(&l_npc_mail, pid, anm_id);
+ res = mPO_receipt_proc(&l_npc_mail, 0);
+ }
+ }
+
+ return res;
+}
+
+s32 mNpc_SendEventBirthdayCard(UNUSED PersonalID_c* pid) {
+ return FALSE;
+}
+
+s32 mNpc_SendEventBirthdayCard2(PersonalID_c* pid, s32 playerNo) {
+ Animal_c* animal = common_data.animals;
+ s32 res = FALSE;
+ s32 idx;
+ s32 i;
+
+ if (pid != NULL && mLd_CheckThisLand(pid->landName, pid->landId) == TRUE) {
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (mNpc_CheckFreeAnimalPersonalID(&animal->id) == FALSE) {
+ idx = mNpc_GetHighestFriendshipIdx(animal->memories, ANIMAL_MEMORY_NUM);
+ if ((idx != -1) && (mPr_CheckCmpPersonalID(pid, &animal->memories[idx].memoryPlayerId) != 0) &&
+ (mNpc_SendBirthdayCard(pid, playerNo, &animal->id) == 1)) {
+ res = TRUE;
+ }
+ }
+
+ animal++;
+ }
+ }
+
+ return res;
+}
+
+void mNpc_GetXmasCardData(Mail_c* mail, PersonalID_c* pid) {
+ UNUSED UNUSED s32 pad;
+ s32 headerBackStart;
+
+ mHandbill_Load_HandbillFromRom(mail->content.header, &headerBackStart, mail->content.footer, mail->content.body,
+ 0xD7);
+ mail->content.headerBackStart = headerBackStart;
+ mail->content.font = 0;
+ mail->content.mailType = 1;
+ mPr_CopyPersonalID(&mail->header.recipient.personalID, pid);
+ mail->header.recipient.type = MAIL_NAME_TYPE_PLAYER;
+ mSP_SelectRandomItem_New(NULL, &mail->present, 1, NULL, 0, 0, 3);
+ mail->content.paperType = 22;
+}
+
+s32 mNpc_SendEventXmasCard(PersonalID_c* pid, s32 playerNo) {
+ UNUSED s32 pad;
+ mHm_hs_c* home;
+ UNUSED s32 pad2;
+ s32 freeSpace;
+ s32 res = FALSE;
+
+ if (mPr_NullCheckPersonalID(pid) == FALSE) {
+ home = &common_data.homes[mHS_get_arrange_idx(playerNo)];
+
+ if (mPr_CheckCmpPersonalID(pid, &home->ownerID) == TRUE) {
+ freeSpace = mMl_chk_mail_free_space(home->mailbox, 10);
+
+ if (freeSpace != -1) {
+ mNpc_GetXmasCardData(&l_npc_mail, pid);
+ mMl_copy_mail(home->mailbox + freeSpace, &l_npc_mail);
+ res = TRUE;
+ }
+ }
+ }
+
+ return res;
+}
+
+void mNpc_SetWordEnding(Animal_c* animal, char* catchphrase) {
+ mem_copy((u8*)animal->catchphrase, (u8*)catchphrase, ANIMAL_CATCHPHRASE_LEN);
+}
+
+char* mNpc_GetWordEnding(Actor* actor) {
+ Animal_c* animalInfo;
+ Animal_c* temp;
+ char* wordEnding;
+
+ if ((actor != NULL) & (actor->part == ACTOR_PART_NPC)) {
+ animalInfo = temp = ((Npc*)actor)->npcInfo.animal;
+ } else {
+ animalInfo = NULL;
+ }
+
+ if ((actor != NULL) && (animalInfo != NULL)) {
+ wordEnding = animalInfo->catchphrase;
+ } else {
+ wordEnding = l_no_ending_npc_ending;
+ }
+
+ return wordEnding;
+}
+
+void mNpc_ResetWordEnding(Actor* actor) {
+ if (actor != NULL && actor->part == ACTOR_PART_NPC) {
+ Animal_c* animal = ((Npc*)actor)->npcInfo.animal;
+ NpcDefaultData* list;
+ u16 idx;
+
+ if (animal != NULL) {
+
+ list = zelda_malloc(SEGMENT_ROM_SIZE(segment_00E03000));
+
+ if (0) {}
+
+ if (list != NULL) {
+ DmaMgr_RequestSyncDebug(list, SEGMENT_ROM_START(segment_00E03000),
+ ALIGN16(SEGMENT_ROM_SIZE(segment_00E03000)), "../m_npc.c", 0xE25);
+ idx = animal->id.npcId & 0xFFF;
+ mString_Load_StringFromRom(animal->catchphrase, ANIMAL_CATCHPHRASE_LEN, list[idx].catchphraseIdx);
+ zelda_free(list);
+ }
+ }
+ }
+}
+
+s32 mNpc_GetFreeEventNpcIdx() {
+ NpcEvent* npcEvent = common_data.npcEvent;
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(common_data.npcEvent); i++) {
+ if (npcEvent->use == FALSE) {
+ return i;
+ }
+
+ npcEvent++;
+ }
+
+ return -1;
+}
+
+s32 mNpc_RegistEventNpc(u16 eventId, u16 textureId, u16 npcId, u16 clothId) {
+ s32 freeIdx = mNpc_GetFreeEventNpcIdx();
+ s32 res = FALSE;
+
+ if (freeIdx != -1) {
+ NpcEvent* npcEvent = &common_data.npcEvent[freeIdx];
+
+ npcEvent->eventId = eventId;
+ npcEvent->textureId = textureId;
+ npcEvent->npcId = npcId;
+ npcEvent->clothId = clothId;
+ npcEvent->exists = FALSE;
+ npcEvent->use = TRUE;
+
+ res = TRUE;
+ }
+
+ return res;
+}
+
+void mNpc_UnRegistEventNpc(u16 eventId) {
+ NpcEvent* savedNpc = common_data.npcEvent;
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(common_data.npcEvent); i++) {
+ if ((savedNpc->use == TRUE) && (savedNpc->eventId == eventId)) {
+ bzero(savedNpc, sizeof(NpcEvent));
+ break;
+ }
+
+ savedNpc++;
+ }
+}
+
+void mNpc_ClearEventNpc() {
+ bzero(common_data.npcEvent, sizeof(common_data.npcEvent));
+}
+
+NpcEvent* mNpc_GetSameEventNpc(u16 eventId) {
+ NpcEvent* npcEvent = common_data.npcEvent;
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(common_data.npcEvent); i++) {
+ if (npcEvent->eventId == eventId) {
+ return npcEvent;
+ }
+
+ npcEvent++;
+ }
+
+ return NULL;
+}
+
+u8 mNpc_GetLooks(u16 npcId) {
+ u8 looks = NPC_LOOKS_GIRL;
+
+ if (ACTOR_FGNAME_GET_F000(npcId) == FGNAME_F000_E) {
+ looks = npc_looks_table[npcId & 0xFFF];
+ }
+
+ return looks;
+}
+
+void mNpc_SetDefAnimalInfo(Animal_c* animal, u16 npcId, u8 looks, NpcDefaultData* defaultData) {
+ if (ACTOR_FGNAME_GET_F000(npcId) == FGNAME_F000_E) {
+ animal->id.npcId = npcId;
+ animal->id.looks = looks;
+ animal->cloth = defaultData->cloth;
+ mString_Load_StringFromRom(animal->catchphrase, ANIMAL_CATCHPHRASE_LEN, defaultData->catchphraseIdx);
+ animal->id.landId = common_data.landInfo.id;
+ mLd_CopyLandName(animal->id.landName, common_data.landInfo.name);
+ }
+}
+
+void mNpc_SetDefAnimal(Animal_c* animal, u16 npcId, NpcDefaultData* defaultData) {
+ s32 idx = npcId & 0xFFF;
+
+ if (ACTOR_FGNAME_GET_F000(npcId) == FGNAME_F000_E) {
+ mNpc_SetDefAnimalInfo(animal, npcId, npc_looks_table[idx], &defaultData[idx]);
+ }
+}
+
+void mNpc_SetHaveAppeared(u16 npcId) {
+ u8* usedTable = common_data.npcUsedTable;
+
+ if (ACTOR_FGNAME_GET_F000(npcId) == FGNAME_F000_E) {
+ s32 idx = npcId & 0xFFF;
+ s32 i = idx / 8;
+
+ if (i < ARRAY_COUNT(common_data.npcUsedTable)) {
+ usedTable += i;
+ idx &= 7;
+ *usedTable |= 1 << idx;
+ }
+ }
+}
+
+s32 mNpc_GetHaveAppeared_idx(s32 idx) {
+ s32 res = TRUE;
+ u8* usedTable = common_data.npcUsedTable;
+ s32 i = idx / 8;
+
+ if (i < ARRAY_COUNT(common_data.npcUsedTable)) {
+ usedTable += i;
+ res = (*usedTable >> (idx & 7)) & 1;
+ }
+
+ return res;
+}
+
+s32 mNpc_GetLooks2NotHaveAppearedNum(u8 id) {
+ s32 i;
+ s32 count = 0;
+
+ if (id < 6) {
+ for (i = 0; i < NPC_NUM; i++) {
+ if ((id == npc_looks_table[i]) && (mNpc_GetHaveAppeared_idx(i) == FALSE)) {
+ count++;
+ }
+ }
+ }
+
+ return count;
+}
+
+void mNpc_ResetHaveAppeared_common(u8* npcUsedTable, Animal_c* animal) {
+ s32 i;
+
+ bzero(npcUsedTable, sizeof(common_data.npcUsedTable));
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (mNpc_CheckFreeAnimalInfo(animal) == FALSE) {
+ mNpc_SetHaveAppeared(animal->id.npcId);
+ }
+
+ animal++;
+ }
+}
+
+void mNpc_ResetHaveAppeared() {
+ s32 i;
+
+ for (i = 0; i < NPC_NUM; i++) {
+ if (mNpc_GetHaveAppeared_idx(i) == FALSE) {
+ break;
+ }
+ }
+
+ if (i == NPC_NUM) {
+ mNpc_ResetHaveAppeared_common(common_data.npcUsedTable, common_data.animals);
+ }
+}
+
+s32 mNpc_GetDefGrowPermission(s32 idx, s8* growList, s32 count) {
+ s32 res = 1;
+
+ if (idx < count) {
+ res = growList[idx];
+ }
+
+ return res;
+}
+
+void mNpc_DecideLivingNpcMax(Animal_c* animal, u8 count, s32 mallocFlag) {
+ UNUSED s32 pad;
+ NpcDefaultData* defList;
+ s8* growList;
+ u8 bitfield = 0;
+ s32 i = 0;
+ u8 looks;
+
+ bzero(fakeTable, sizeof(fakeTable));
+ mNpc_MakeRandTable(fakeTable, ARRAY_COUNT(fakeTable), ARRAY_COUNT(fakeTable));
+
+ if (mallocFlag == 0) {
+ defList = malloc(SEGMENT_ROM_SIZE(segment_00E03000));
+ growList = malloc(ALIGN2(SEGMENT_ROM_SIZE(segment_00E0D000)));
+ } else {
+ defList = zelda_malloc(SEGMENT_ROM_SIZE(segment_00E03000));
+ growList = zelda_malloc(ALIGN2(SEGMENT_ROM_SIZE(segment_00E0D000)));
+ }
+
+ DmaMgr_RequestSyncDebug(defList, SEGMENT_ROM_START(segment_00E03000), SEGMENT_ROM_SIZE(segment_00E03000),
+ "../m_npc.c", 4083);
+ DmaMgr_RequestSyncDebug(growList, SEGMENT_ROM_START(segment_00E0D000), ALIGN2(SEGMENT_ROM_SIZE(segment_00E0D000)),
+ "../m_npc.c", 4085);
+
+ while (count) {
+ if (animal == NULL) {
+ break;
+ }
+
+ if (animal->id.npcId == 0) {
+ s32 idx = fakeTable[i];
+ s32 growPerm = mNpc_GetDefGrowPermission(idx, growList, ALIGN2(SEGMENT_ROM_SIZE(segment_00E0D000)));
+
+ if (growPerm == 0) {
+ looks = npc_looks_table[idx];
+ if (((bitfield >> looks) & 1) == 0) {
+ mNpc_SetDefAnimal(animal, idx | 0xE000, defList);
+ bitfield |= (1 << looks);
+ mNpc_SetHaveAppeared(idx | 0xE000);
+ animal++;
+ count--;
+ }
+ } else if (growPerm == -1) {
+ mNpc_SetHaveAppeared(idx | 0xE000);
+ }
+ } else {
+ count--;
+ animal++;
+ }
+ i++;
+ }
+
+ if (mallocFlag == 0) {
+ free(defList);
+ free(growList);
+ } else {
+ zelda_free(defList);
+ zelda_free(growList);
+ }
+}
+
+void mNpc_SetAnimalTitleDemo(DemoNpc* demo, Animal_c* animal, Game* game) {
+ GameAlloc* alloc = NULL;
+ NpcDefaultData* defList;
+ s32 i;
+
+ if (game != NULL) {
+ alloc = &game->alloc;
+ defList = gamealloc_malloc(alloc, SEGMENT_ROM_SIZE(segment_00E03000));
+ } else {
+ defList = zelda_malloc(SEGMENT_ROM_SIZE(segment_00E03000));
+ }
+
+ DmaMgr_RequestSyncDebug(defList, SEGMENT_ROM_START(segment_00E03000), SEGMENT_ROM_SIZE(segment_00E03000),
+ "../m_npc.c", 0x1055);
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ mNpc_SetDefAnimal(animal, demo->npcName, defList);
+ animal->homeInfo.typeUnused = 0;
+ animal->homeInfo.blockX = demo->blockX;
+ animal->homeInfo.blockZ = demo->blockZ;
+ animal->homeInfo.utX = demo->utX;
+ animal->homeInfo.utZ = demo->utZ;
+
+ animal++;
+ demo++;
+ }
+
+ if (defList != NULL) {
+ if (game != NULL) {
+ gamealloc_free(alloc, defList);
+ } else {
+ zelda_free(defList);
+ }
+ }
+}
+
+s32 mNpc_GetReservedUtNum(s32* utX, s32* utZ, u16* item) {
+ f32 reserveNum = 0.0f;
+ s32 rand;
+ s32 res = FALSE;
+ s32 i;
+
+ for (i = 0; i < UT_TOTAL_NUM; i++) {
+ if ((*item >= 0x5810 && *item < 0x5825) || *item == 0xF0EE) {
+ reserveNum++;
+ }
+
+ item++;
+ }
+
+ if (reserveNum > 0.0f) {
+ item -= UT_TOTAL_NUM;
+ rand = RANDOM(reserveNum);
+
+ for (i = 0; i < UT_TOTAL_NUM; i++) {
+ if ((*item >= 0x5810 && *item < 0x5825) || *item == 0xF0EE) {
+ if (rand == 0) {
+ *utX = i % UT_Z_NUM;
+ *utZ = i / UT_X_NUM;
+ res = TRUE;
+
+ break;
+ } else {
+ rand--;
+ }
+ }
+
+ item++;
+ }
+ }
+
+ return res;
+}
+
+s32 mNpc_BlockNum2ReservedUtNum(s32* utX, s32* utZ, s32 bx, s32 bz) {
+ u16* items = mFI_BkNumtoUtFGTop(bx, bz);
+ s32 res = FALSE;
+
+ if (items != NULL) {
+ res = mNpc_GetReservedUtNum(utX, utZ, items);
+ }
+
+ return res;
+}
+
+void mNpc_MakeReservedListBeforeFieldct(Anmhome_c* reserved, s32 reservedNum, u8* reservedCount) {
+ Foreground* fg = &common_data.foreground[0][0];
+ Anmhome_c* reservedp = reserved;
+ u16* item;
+ u8 num = 0;
+ u8 i;
+ u8 j;
+ u8 k;
+ u8 l;
+
+ for (i = 0; i < reservedNum; i++) {
+ reserved->blockX = -1;
+ reserved->blockZ = -1;
+ reserved->utX = -1;
+ reserved->utZ = -1;
+ reserved++;
+ }
+
+ reserved = reservedp;
+ for (i = 0; i < FG_BLOCK_Z_NUM; i++) {
+ for (j = 0; j < FG_BLOCK_X_NUM; j++) {
+ item = &fg->items[0][0];
+
+ for (k = 0; k < UT_Z_NUM; k++) {
+ for (l = 0; l < UT_X_NUM; l++) {
+ if ((*item >= 0x5810) && (*item < 0x5825)) {
+ num++;
+ reserved->blockX = j + 1;
+ reserved->blockZ = i + 1;
+ reserved->utX = l;
+ reserved->utZ = k;
+ reserved++;
+ if (num >= reservedNum) {
+ *reservedCount = num;
+ return;
+ }
+ }
+
+ item++;
+ }
+ }
+
+ fg++;
+ }
+ }
+
+ *reservedCount = num;
+}
+
+void mNpc_MakeReservedListAfterFieldct(Anmhome_c* reserved, s32 reservedNum, u8* reserved_count, u8 bxMax, u8 bzMax) {
+ FieldMakeBlockInfo* blockInfo = mFI_GetBlockTopP();
+ Anmhome_c* reservedp = reserved;
+ u16* item;
+ u8 num = 0;
+ u8 i;
+ u8 j;
+ u8 k;
+ u8 l;
+
+ for (i = 0; i < reservedNum; i++) {
+ reserved->blockX = -1;
+ reserved->blockZ = -1;
+ reserved->utX = -1;
+ reserved->utZ = -1;
+ reserved++;
+ }
+
+ reserved = reservedp;
+ for (i = 0; i < bzMax; i++) {
+ for (j = 0; j < bxMax; j++) {
+ item = blockInfo->fgInfo.itemsPtr;
+
+ for (k = 0; k < UT_Z_NUM; k++) {
+ for (l = 0; l < UT_X_NUM; l++) {
+ if (((*item >= 0x5810) && (*item < 0x5825))) {
+ num++;
+ reserved->blockX = j;
+ reserved->blockZ = i;
+ reserved->utX = l;
+ reserved->utZ = k;
+ reserved++;
+ if (num >= reservedNum) {
+ *reserved_count = num;
+ return;
+ }
+ }
+
+ item++;
+ }
+ }
+
+ blockInfo++;
+ }
+ }
+
+ *reserved_count = num;
+}
+
+void mNpc_BuildHouseBeforeFieldct(u16 npcId, s32 bx, s32 bz, s32 utX, s32 utZ) {
+ static s32 ut_d[9][2] = { { 0, 0 }, { -1, 1 }, { 0, 1 }, { 1, 1 }, { -1, 0 },
+ { 1, 0 }, { -1, -1 }, { 0, -1 }, { 1, -1 } };
+
+ static u16 set_fg[9] = {
+ 0, 0xA012, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ };
+
+ u16* deposit;
+ Foreground* fg;
+ s32 x;
+ s32 z;
+ s32 i;
+ u16 house = npcId - 0x10000 + 0x7000; // this shifts it to the house range 0x50XX
+
+ if (bx >= 0 && bx < FG_BLOCK_X_NUM && bz >= 0 && bz < FG_BLOCK_Z_NUM && utX > 0 && utX < (UT_X_NUM - 1) &&
+ utZ > 0 && utZ < (UT_Z_NUM - 1)) {
+ set_fg[0] = house;
+ fg = &common_data.foreground[bz][bx];
+
+ deposit = mFI_GetDepositP(bx + 1, bz + 1);
+
+ for (i = 0; i < ARRAY_COUNT(set_fg); i++) {
+ x = ut_d[i][0] + utX;
+ z = ut_d[i][1] + utZ;
+
+ mPB_keep_item(fg->items[z][x]);
+ if (deposit != NULL) {
+ mFI_BlockDepositOFF(deposit, x, z);
+ }
+
+ fg->items[z][x] = set_fg[i];
+ }
+ }
+}
+
+void mNpc_DestroyHouse(Anmhome_c* home) {
+ u8 bx = home->blockX - 1;
+ u8 bz = home->blockZ - 1;
+ u8 utX = home->utX;
+ u8 utZ = home->utZ - 1;
+
+ if (bx < FG_BLOCK_X_NUM && bz < FG_BLOCK_Z_NUM && utX > 0 && utX < (UT_X_NUM - 1) && utZ > 0 &&
+ utZ < (UT_Z_NUM - 1)) {
+ u16 reserveNo = mFM_GetReseveName(home->blockX, home->blockZ);
+
+ common_data.foreground[bz][bx].items[utZ][utX] = reserveNo;
+ common_data.foreground[bz][bx].items[utZ + 1][utX - 1] = 0;
+ common_data.foreground[bz][bx].items[utZ + 1][utX] = 0;
+ common_data.foreground[bz][bx].items[utZ + 1][utX + 1] = 0;
+ common_data.foreground[bz][bx].items[utZ][utX - 1] = 0;
+ common_data.foreground[bz][bx].items[utZ][utX + 1] = 0;
+ common_data.foreground[bz][bx].items[utZ - 1][utX - 1] = 0;
+ common_data.foreground[bz][bx].items[utZ - 1][utX] = 0;
+ common_data.foreground[bz][bx].items[utZ - 1][utX + 1] = 0;
+ }
+}
+
+void mNpc_SetNpcHome(Animal_c* animal, Anmhome_c* reserved, u8 reserved_num) {
+ Anmhome_c* homeInfo;
+ s32 i;
+ s32 idx;
+
+ if (reserved_num > ARRAY_COUNT(fake_table)) {
+ reserved_num = ARRAY_COUNT(fake_table);
+ }
+
+ bzero(fake_table, sizeof(fake_table));
+ mNpc_MakeRandTable(fake_table, reserved_num, ARRAY_COUNT(fake_table) / 2);
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (i >= reserved_num) {
+ break;
+ }
+
+ homeInfo = &animal->homeInfo;
+ if ((ACTOR_FGNAME_GET_F000(animal->id.npcId) == FGNAME_F000_E) && homeInfo->blockX == 0xFF &&
+ homeInfo->blockZ == 0xFF) {
+ idx = fake_table[i];
+
+ homeInfo->blockX = reserved[idx].blockX;
+ homeInfo->blockZ = reserved[idx].blockZ;
+ homeInfo->utX = reserved[idx].utX;
+ homeInfo->utZ = reserved[idx].utZ + 1;
+ mNpc_BuildHouseBeforeFieldct(animal->id.npcId, homeInfo->blockX - 1, homeInfo->blockZ - 1, homeInfo->utX,
+ reserved[idx].utZ);
+ }
+ animal++;
+ }
+}
+
+void mNpc_InitNpcData() {
+ UNUSED s32 pad;
+ u8 reservedNum = 0;
+
+ mNpc_MakeReservedListBeforeFieldct(reserved, ARRAY_COUNT(reserved), &reservedNum);
+ mNpc_SetNpcHome(common_data.animals, reserved, reservedNum);
+}
+
+void mNpc_InitNpcList() {
+ NpcList* npclist = common_data.npclist;
+ s32 i;
+
+ if (npclist != NULL) {
+ bzero(npclist, ANIMAL_NUM_MAX * sizeof(NpcList));
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ npclist->fieldName = 0xFFFF;
+ mQst_ClearQuestInfo(&npclist->questInfo);
+ npclist->houseData.type = 0xFF;
+ npclist->houseData.palette = 0xFF;
+ npclist->houseData.wallId = 0xFF;
+ npclist->houseData.floorId = 0xFF;
+ npclist->houseData.mainLayerId = 203;
+
+ npclist++;
+ }
+ }
+}
+
+void mNpc_SetNpcList(NpcList* npclist, Animal_c* animal, s32 count, s32 mallocFlag) {
+ NpcHouseData* houseData;
+ NpcHouseData* newHouseData;
+ xyz_t* homePos;
+ xyz_t* pos;
+ s32 houseId;
+ f32 z;
+ Anmhome_c* homeInfo;
+ f32 x;
+ u32 houseDataSize;
+ s32 i;
+ s32 npcId;
+
+ houseDataSize = SEGMENT_ROM_SIZE(segment_00E02000);
+ if (mallocFlag == 0) {
+ houseData = malloc(houseDataSize);
+ } else {
+ houseData = zelda_malloc(houseDataSize);
+ }
+ DmaMgr_RequestSyncDebug(houseData, SEGMENT_ROM_START(segment_00E02000), houseDataSize, "../m_npc.c", 0x1328);
+
+ for (i = 0; i < count; i++) {
+
+ homeInfo = &animal->homeInfo;
+ if ((ACTOR_FGNAME_GET_F000(animal->id.npcId) == FGNAME_F000_E) && homeInfo->blockX != 0xFF) {
+ npcId = animal->id.npcId;
+ houseId = animal->id.npcId & 0xFFF;
+ newHouseData = &npclist->houseData;
+ homePos = &npclist->homePosition;
+ pos = &npclist->position;
+ if (0) {}
+ npclist->name = npcId;
+
+ homePos->x = homeInfo->blockX * 640.0f;
+ homePos->z = homeInfo->blockZ * 640.0f;
+ mFI_UtNum2PosXZInBk(&x, &z, homeInfo->utX, homeInfo->utZ);
+
+ homePos->x += x;
+ homePos->z += z;
+ homePos->y = 0.0f;
+
+ pos->x = homePos->x;
+ pos->y = homePos->y;
+ pos->z = homePos->z;
+
+ npclist->appearFlag = TRUE;
+ npclist->rewardFurniture = 0;
+
+ newHouseData->type = houseData[houseId].type;
+ newHouseData->palette = houseData[houseId].palette;
+ newHouseData->wallId = houseData[houseId].wallId;
+ newHouseData->floorId = houseData[houseId].floorId;
+ newHouseData->mainLayerId = houseData[houseId].mainLayerId;
+ newHouseData->secondaryLayerId = houseData[houseId].secondaryLayerId;
+ }
+
+ npclist++;
+ animal++;
+ }
+
+ if (mallocFlag == 0) {
+ free(houseData);
+ } else {
+ zelda_free(houseData);
+ }
+}
+
+void mNpc_SetNpcinfo(Actor* actor, s8 npcInfoIdx) {
+ if (actor->part == ACTOR_PART_NPC) {
+ Npc* npc = (Npc*)actor;
+ u16 npcId = actor->fgName;
+
+ if (ACTOR_FGNAME_GET_F000(npc->actor.fgName) == FGNAME_F000_D) {
+ NpcEvent* eventNpc = mNpc_GetSameEventNpc(npcId);
+
+ if (eventNpc != NULL) {
+ npcInfoIdx = mNpc_SearchAnimalinfo(common_data.animals, eventNpc->npcId, ANIMAL_NUM_MAX);
+ }
+ }
+
+ if (npcInfoIdx >= 0 && npcInfoIdx < ANIMAL_NUM_MAX) {
+ npc->npcInfo.animal = &common_data.animals[npcInfoIdx];
+ npc->npcInfo.list = &common_data.npclist[npcInfoIdx];
+ } else {
+ npc->npcInfo.animal = NULL;
+ npc->npcInfo.list = NULL;
+ }
+ }
+}
+
+void mNpc_AddNpc_inNpcRoom(FieldMakeMoveActor* moveActor, u8 bx, u8 bz) {
+ s32 animalId;
+ s32 idx;
+ u16 fieldId;
+ u16 houseOwnerId;
+ u8* animalIdInField;
+ UNUSED s32 pad;
+ u16 currentNpc;
+ s32 npcId;
+
+ if (moveActor != NULL) {
+ fieldId = mFI_GetFieldId();
+ idx = func_8008BE00_jp(moveActor, 16);
+ if (idx != -1) {
+ moveActor = &moveActor[idx];
+ if ((fieldId & 0xF000) == 0x4000) {
+ houseOwnerId = common_data.houseOwnerName;
+ if ((idx < ANIMAL_NUM_MAX) && (houseOwnerId != 0xFFFF) && (houseOwnerId != 0)) {
+ if (mEvNM_CheckJointEvent(houseOwnerId) != 1) {
+ animalId = mNpc_SearchAnimalinfo(common_data.animals, houseOwnerId, ANIMAL_NUM_MAX);
+ if (animalId != -1) {
+ moveActor->nameId = houseOwnerId;
+ moveActor->utX = 4;
+ moveActor->utZ = 7;
+ moveActor->npcId = animalId;
+ moveActor->arg = -1;
+ mFI_SetMoveActorBitData_ON(idx, bx, bz);
+ }
+ }
+ }
+ } else if (fieldId == 0x300A) {
+ animalIdInField = func_8008033C_jp(0xE, 0xF);
+ if (animalIdInField != NULL) {
+ npcId = *animalIdInField;
+ currentNpc = common_data.animals[npcId].id.npcId;
+ func_80082BD8_jp(&currentNpc, 0xE, npcId, 0);
+ moveActor->nameId = currentNpc;
+ moveActor->utX = 4;
+ moveActor->utZ = 7;
+ moveActor->npcId = npcId;
+ moveActor->arg = -1;
+ mFI_SetMoveActorBitData_ON(idx, bx, bz);
+ }
+ }
+ }
+ }
+}
+
+void mNpc_RenewalNpcRoom(s16* wallFloor) {
+ s32 fieldId = mFI_GetFieldId();
+ u16 ownerName = common_data.houseOwnerName;
+ s32 wallId;
+ s32 floorId;
+ s32 npcIdx;
+
+ if ((fieldId & 0xF000) == 0x4000) {
+ if ((ownerName != 0) && (ownerName != 0xFFFF)) {
+ npcIdx = mNpc_SearchAnimalinfo(common_data.animals, ownerName, ANIMAL_NUM_MAX);
+ wallId = common_data.npclist[npcIdx].houseData.wallId;
+ floorId = common_data.npclist[npcIdx].houseData.floorId;
+ *wallFloor = floorId | (wallId << 8);
+ { UNUSED s32 scopedTemp; }
+ return;
+ }
+ }
+ *wallFloor = 0;
+}
+
+void mNpc_RenewalSetNpc(Actor* actor) {
+ Npc* npc = (Npc*)actor;
+
+ if (npc->npcInfo.list != NULL) {
+ s32 fieldId = mFI_GetFieldId();
+ NpcList* npcList = npc->npcInfo.list;
+
+ if ((fieldId & 0xF000) == 0) {
+ xyz_t_move(&npcList->position, &npc->actor.world.pos);
+ npcList->appearFlag = TRUE;
+ }
+ } else {
+ mFI_MyMoveActorBitData_ON(actor);
+ }
+}
+
+s32 mNpc_GetFriendAnimalNum(PersonalID_c* pid) {
+ Animal_c* animal = common_data.animals;
+ s32 num = 0;
+ s32 i;
+
+ if (pid != NULL) {
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (mNpc_CheckFreeAnimalPersonalID(&animal->id) == FALSE &&
+ mNpc_GetAnimalMemoryIdx(pid, animal->memories, ANIMAL_MEMORY_NUM) != -1) {
+ num++;
+ }
+
+ animal++;
+ }
+ }
+
+ return num;
+}
+
+s32 mNpc_CheckFriendAllAnimal(PersonalID_c* pid) {
+ s32 nowNpcMax = common_data.nowNpcMax;
+ s32 friendNum = mNpc_GetFriendAnimalNum(pid);
+
+ if (nowNpcMax <= friendNum) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+s32 mNpc_CheckSelectFurniture(u16 item) {
+ s32 res = FALSE;
+
+ if (((item < 0x17AC) || (item >= 0x1BA8)) && ((item < 0x1CA8) || (item >= 0x1D28)) &&
+ ((item < 0x1BA8) || (item >= 0x1C28)) && ((item < 0x1C28) || (item >= 0x1CA8)) &&
+ ((item < 0x15B0) || (item >= 0x17AC)) && ((item < 0x1E3C) || (item >= 0x1EA0)) &&
+ ((item < 0x1D28) || (item >= 0x1D44))) {
+ res = TRUE;
+ }
+ return res;
+}
+
+u16 mNpc_DecideNpcFurniture(FieldMakeFGData** data, NpcList* npcList, s32 count) {
+ u16 layerId = npcList->houseData.mainLayerId;
+ s32 idx = layerId - count;
+ u16* fgItems;
+ s32 i;
+ s32 j;
+ u8 num = 0;
+
+ if (idx < 0) {
+ idx = 0;
+ }
+ fgItems = data[idx]->items[0];
+
+ for (i = 0; i < 10; i++) {
+ for (j = 0; j < 10; j++) {
+ if ((ACTOR_FGNAME_GET_F000(*fgItems) == FGNAME_F000_1) && (mNpc_CheckSelectFurniture(*fgItems) == TRUE)) {
+ num++;
+ }
+ fgItems++;
+ }
+ fgItems += UT_X_NUM - 10;
+ }
+
+ if (num > 0) {
+ num = RANDOM(num);
+ fgItems = data[idx]->items[0];
+
+ for (i = 0; i < 10; i++) {
+ for (j = 0; j < 10; j++) {
+ if ((ACTOR_FGNAME_GET_F000(*fgItems) == FGNAME_F000_1) &&
+ (mNpc_CheckSelectFurniture(*fgItems) == TRUE)) {
+ if (num <= 0) {
+ return *fgItems;
+ }
+ num--;
+ }
+ fgItems++;
+ }
+ fgItems += UT_X_NUM - 10;
+ }
+ }
+
+ return 0;
+}
+
+void mNpc_SetNpcFurnitureRandom(FieldMakeFGData** data, s32 base) {
+ NpcList* npclist = common_data.npclist;
+ Animal_c* animal = common_data.animals;
+ s32 i;
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (mNpc_CheckFreeAnimalPersonalID(&animal->id) == FALSE) {
+ npclist->rewardFurniture = mNpc_DecideNpcFurniture(data, npclist, base);
+ }
+
+ npclist++;
+ animal++;
+ }
+}
+
+u16 mNpc_GetNpcFurniture(AnmPersonalID_c* anmId) {
+ u16 furniture = 0;
+ s32 idx = mNpc_SearchAnimalPersonalID(anmId);
+
+ if (idx != -1) {
+ furniture = common_data.npclist[idx].rewardFurniture;
+ }
+ return furniture;
+}
+
+void mNpc_ClearInAnimal() {
+ mNpc_ClearAnimalInfo(&l_mnpc_remove_in_animal);
+}
+
+Animal_c* mNpc_GetInAnimalP() {
+ return &l_mnpc_remove_in_animal;
+}
+
+s32 mNpc_DecideRemoveAnimalNo_Friend(Animal_c* animal, s32 metFlag) {
+ PrivateInfo* priv = common_data.saveFilePrivateInfo;
+ s32 res = -1;
+ s32 playerNumber = 0;
+ s32 possibleNum = 0;
+ s32 met;
+ s32 i;
+ s32 j;
+ u16 bitfield = 0;
+
+ for (i = 0; i < PLAYER_NUM; i++) {
+ if (mPr_NullCheckPersonalID(&priv->playerId) == FALSE) {
+ playerNumber++;
+ }
+ priv++;
+ }
+
+ if (playerNumber > 0) {
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (mNpc_CheckFreeAnimalInfo(animal) == FALSE) {
+ priv = common_data.saveFilePrivateInfo;
+ met = 0;
+
+ for (j = 0; j < PLAYER_NUM; j++) {
+ if (mPr_NullCheckPersonalID(&priv->playerId) == FALSE) {
+ if (mNpc_GetAnimalMemoryIdx(&priv->playerId, animal->memories, ANIMAL_MEMORY_NUM) == -1) {
+ break;
+ }
+
+ met++;
+ }
+
+ priv++;
+ }
+
+ if (metFlag == TRUE) {
+ if (met == playerNumber) {
+ possibleNum++;
+ bitfield |= (1 << i);
+ }
+ } else if (met > 0) {
+ possibleNum++;
+ bitfield |= (1 << i);
+ }
+ }
+
+ animal++;
+ }
+ }
+
+ if (possibleNum > 0) {
+ s32 selected = RANDOM(possibleNum);
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (((bitfield >> i) & 1) == 1) {
+ if (selected <= 0) {
+ res = i;
+ break;
+ } else {
+ selected--;
+ }
+ }
+ }
+ }
+
+ return res;
+}
+
+u8 mNpc_DecideRemoveAnimalNo(Animal_c* animal, s32 max) {
+ u8 count = 0;
+ s32 selected = RANDOM(max);
+ s32 i;
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (mNpc_CheckFreeAnimalInfo(animal) == FALSE) {
+ selected--;
+ }
+ if (selected <= 0) {
+ break;
+ }
+ count++;
+ animal++;
+ }
+
+ return count;
+}
+
+void mNpc_SetRemoveAnimalNo(Animal_c* animal) {
+ u8* removalIdx = &common_data.removeAnimalIdx;
+ u8 nowMax = common_data.nowNpcMax;
+
+ if ((nowMax >= 6) && (*removalIdx == 0xFF)) {
+ s32 removeNo = mNpc_DecideRemoveAnimalNo_Friend(animal, TRUE);
+
+ if (removeNo == -1) {
+ removeNo = mNpc_DecideRemoveAnimalNo_Friend(animal, FALSE);
+ if (removeNo == -1) {
+ removeNo = mNpc_DecideRemoveAnimalNo(animal, nowMax);
+ }
+ }
+
+ if (removeNo != -1) {
+ *removalIdx = removeNo;
+ }
+ }
+}
+
+s32 mNpc_CheckGoodbyAnimalMemoryNum(Animal_c* a0, Animal_c* a1) {
+ Anmmem_c* memories0 = a0->memories;
+ Anmmem_c* memories1 = a1->memories;
+ s32 res = 0;
+ s32 res0;
+ s32 res1;
+
+ res0 = mNpc_GetAnimalMemoryNum(memories0, ANIMAL_MEMORY_NUM);
+ res1 = mNpc_GetAnimalMemoryNum(memories1, ANIMAL_MEMORY_NUM);
+
+ if (res1 > res0) {
+ res = 1;
+ } else if (res1 == res0) {
+ res0 = mNpc_GetAnimalMemoryLetterNum(memories0, ANIMAL_MEMORY_NUM);
+ res1 = mNpc_GetAnimalMemoryLetterNum(memories1, ANIMAL_MEMORY_NUM);
+
+ if (res1 > res0) {
+ res = 1;
+ } else if (res1 == res0) {
+ res0 = mNpc_GetAnimalMemoryLandKindNum(memories0, ANIMAL_MEMORY_NUM);
+ res1 = mNpc_GetAnimalMemoryLandKindNum(memories1, ANIMAL_MEMORY_NUM);
+
+ if (res1 > res0) {
+ res = 1;
+ } else if (res1 == res0) {
+ res0 = mNpc_GetSameLooksNum(a0->id.looks);
+ res1 = mNpc_GetSameLooksNum(a1->id.looks);
+
+ if (res1 < res0) {
+ res = 1;
+ } else {
+ res = -1;
+ }
+ }
+ }
+ }
+
+ return res;
+}
+
+s32 mNpc_GetGoodbyAnimalIdx() {
+ UNUSED s32 pad;
+ Animal_c* animal = common_data.animals;
+ Animal_c* otherAnimal = NULL;
+ s32 res0;
+ s32 res1;
+ u16 bitfield = 0;
+ s32 candidate = 0;
+ s32 goodbyeIdx = -1;
+ s32 i;
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++, animal++) {
+ if ((i != (u32)&common_data.removeAnimalIdx) && (mNpc_CheckFreeAnimalInfo(animal) == FALSE)) {
+ if (otherAnimal != NULL) {
+ if (mNpc_CheckRemoveExp(animal) == 0) {
+ if (mNpc_CheckRemoveExp(otherAnimal) != 0) {
+ candidate = 1;
+ bitfield = (1 << i);
+ otherAnimal = animal;
+ goodbyeIdx = i;
+ } else {
+ res1 = mNpc_CheckGoodbyAnimalMemoryNum(animal, otherAnimal);
+ switch (res1) {
+ case -1:
+ candidate++;
+ bitfield |= (1 << i);
+ break;
+ case 1:
+ candidate = 1;
+ bitfield = (1 << i);
+ otherAnimal = animal;
+ goodbyeIdx = i;
+ break;
+ }
+ }
+ } else if (mNpc_CheckRemoveExp(otherAnimal) != 0) {
+ res0 = mNpc_GetRemoveTime(animal);
+ res1 = mNpc_GetRemoveTime(otherAnimal);
+ if (res0 < res1) {
+ candidate = 1;
+ bitfield = (1 << i);
+ otherAnimal = animal;
+ goodbyeIdx = i;
+ } else if (res1 == res0) {
+ res1 = mNpc_CheckGoodbyAnimalMemoryNum(animal, otherAnimal);
+ switch (res1) {
+ case -1:
+ candidate++;
+ bitfield |= (1 << i);
+ break;
+ case 1:
+ candidate = 1;
+ bitfield = (1 << i);
+ otherAnimal = animal;
+ goodbyeIdx = i;
+ break;
+ }
+ }
+ }
+ } else {
+ candidate = 1;
+ bitfield = (1 << i);
+ otherAnimal = animal;
+ goodbyeIdx = i;
+ }
+ }
+ }
+
+ if (candidate >= 2) {
+ s32 rand = RANDOM(candidate);
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (((candidate >> i) & 1) == 1) {
+ if (rand == 0) {
+ goodbyeIdx = i;
+ break;
+ } else {
+ rand--;
+ }
+ }
+ }
+ }
+ return goodbyeIdx;
+}
+
+void mNpc_ClearGoodbyMail(AnmGoodbyeMail* mail) {
+ mNpc_ClearAnimalPersonalID(&mail->id);
+ mail->deliverTo = 0;
+}
+
+void mNpc_FirstClearGoodbyMail() {
+ mNpc_ClearGoodbyMail(&l_mnpc_goodby_mail);
+}
+
+void mNpc_SetGoodbyAnimalMail(AnmGoodbyeMail* mail, Animal_c* animal) {
+ PrivateInfo* priv = common_data.saveFilePrivateInfo;
+ s32 i;
+
+ if ((animal != NULL) && (mNpc_CheckFreeAnimalPersonalID(&animal->id) == FALSE)) {
+ mNpc_CopyAnimalPersonalID(&mail->id, &animal->id);
+
+ for (i = 0; i < PLAYER_NUM; i++) {
+ if (mPr_NullCheckPersonalID(&priv->playerId) == FALSE) {
+ mail->deliverTo |= 1 << i;
+ }
+ priv++;
+ }
+ }
+}
+
+s32 mNpc_SetGoodbyMailData(Mail_c* mail, PersonalID_c* pid, AnmPersonalID_c* anm_id) {
+ s32 mailNo;
+ s32 res = FALSE;
+
+ if (anm_id->looks < NPC_LOOKS_NUM) {
+ mailNo = (anm_id->looks * 3) + 0x20E;
+ mailNo += mQst_GetRandom(3);
+ mNpc_GetNpcWorldNameAnm(Goodby_animal_name, anm_id);
+ mHandbill_Set_free_str(0, pid->playerName, PLAYER_NAME_LEN);
+ mHandbill_Set_free_str(1, Goodby_animal_name, ANIMAL_NAME_LEN);
+ mHandbill_Set_free_str(3, common_data.landInfo.name, LAND_NAME_SIZE);
+ mNpc_LoadMailDataCommon2(mail, pid, anm_id, 0, mNpc_GetPaperType(), mailNo);
+ res = TRUE;
+ }
+
+ return res;
+}
+
+s32 mNpc_SendGoodbyAnimalMailOne(Mail_c* mail, PrivateInfo* priv, s32 playerNo, AnmPersonalID_c* anmId) {
+ mHm_hs_c* home;
+ UNUSED s32 pad;
+ s32 res = FALSE;
+
+ home = &common_data.homes[mHS_get_arrange_idx(playerNo)];
+
+ if ((mPr_NullCheckPersonalID(&priv->playerId) == FALSE) &&
+ (mPr_CheckCmpPersonalID(&priv->playerId, &home->ownerID) == TRUE)) {
+ s32 freeSpace = mMl_chk_mail_free_space(home->mailbox, HOME_MAILBOX_SIZE);
+ if (freeSpace != -1) {
+ if (mNpc_SetGoodbyMailData(mail, &priv->playerId, anmId) == TRUE) {
+ mMl_copy_mail(&home->mailbox[freeSpace], mail);
+ res = TRUE;
+ }
+ } else if ((mPO_get_keep_mail_sum() < 5) && (mNpc_SetGoodbyMailData(mail, &priv->playerId, anmId) == TRUE)) {
+ res = mPO_receipt_proc(mail, 0);
+ }
+ }
+ return res;
+}
+
+void mNpc_SendGoodbyAnimalMail(AnmGoodbyeMail* mail) {
+ PrivateInfo* priv = common_data.saveFilePrivateInfo;
+ s32 i;
+
+ if (mNpc_CheckFreeAnimalPersonalID(&mail->id) == FALSE) {
+ for (i = 0; i < PLAYER_NUM; i++) {
+ if ((((mail->deliverTo >> i) & 1) == 1) &&
+ (mNpc_SendGoodbyAnimalMailOne(&l_npc_mail, priv, i, &mail->id) == TRUE)) {
+ mail->deliverTo &= ~(1 << i);
+ }
+ priv++;
+ }
+
+ if (mail->deliverTo == 0) {
+ mNpc_ClearGoodbyMail(mail);
+ }
+ }
+}
+
+void mNpc_SendRegisteredGoodbyMail() {
+ mNpc_SendGoodbyAnimalMail(&l_mnpc_goodby_mail);
+}
+
+void mNpc_GetRemoveAnimal(Animal_c* transferAnimal, s32 movingOut) {
+ PrivateInfo* priv;
+ UNUSED s32 pad[4];
+ s32 newAnimal;
+ Animal_c* animal;
+ s32 freeAnimalIdx;
+ u8* removeAnimalIdx = &common_data.removeAnimalIdx;
+ u8* nowMax = &common_data.nowNpcMax;
+ s32 i;
+
+ animal = common_data.animals;
+ newAnimal = TRUE;
+ priv = common_data.privateInfo;
+ if (mLd_PlayerManKindCheck() == 0) {
+ if (movingOut == 1) {
+ if (*removeAnimalIdx != 0xFF) {
+ animal = &common_data.animals[*removeAnimalIdx];
+ animal->isMoving = FALSE;
+ mNpc_CopyAnimalInfo(transferAnimal, animal);
+ mNpc_DestroyHouse(&animal->homeInfo);
+ mNpc_ClearAnimalInfo(animal);
+ *removeAnimalIdx = 0xFF;
+ (*nowMax)--;
+ }
+ }
+ } else {
+ if ((mNpc_CheckFreeAnimalInfo(transferAnimal) == FALSE) && (transferAnimal->isMoving == 0)) {
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (transferAnimal->id.npcId == animal->id.npcId) {
+ newAnimal = 0;
+ break;
+ }
+ animal++;
+ }
+
+ if (transferAnimal->id.npcId == common_data.lastRemovedAnimalId.npcId) {
+ newAnimal = FALSE;
+ }
+ } else {
+ newAnimal = FALSE;
+ }
+
+ if (newAnimal == TRUE) {
+ animal = common_data.animals;
+ freeAnimalIdx = mNpc_GetFreeAnimalInfo(common_data.animals, ANIMAL_NUM_MAX);
+ if (freeAnimalIdx == -1) {
+ animal += mNpc_GetGoodbyAnimalIdx();
+ mNpc_DestroyHouse(&animal->homeInfo);
+ mNpc_SetGoodbyAnimalMail(&l_mnpc_goodby_mail, animal);
+ mNpc_SendRegisteredGoodbyMail();
+ } else {
+ animal += freeAnimalIdx;
+ mNpc_AddNowNpcMax(&common_data.nowNpcMax);
+ }
+ mNpc_ClearAnimalInfo(animal);
+ mNpc_CopyAnimalInfo(animal, transferAnimal);
+ animal->homeInfo.blockX = 0xFF;
+ animal->homeInfo.blockZ = 0xFF;
+ animal->homeInfo.utX = 0xFF;
+ animal->homeInfo.utZ = 0xFF;
+ mLd_CopyLandName(animal->previousLandName, common_data.privateInfo->playerId.landName);
+ animal->previousLandId = common_data.privateInfo->playerId.landId;
+ mQst_ClearContest(&animal->contestQuest);
+ transferAnimal->isMoving = 1;
+ priv->animalMemory.npcId = animal->id.npcId;
+ mLd_CopyLandName(priv->animalMemory.landName, mLd_GetLandName());
+ mNpc_SetHaveAppeared(animal->id.npcId);
+ }
+ }
+}
+
+s32 mNpc_CheckBuildHouse(s32 blockX, s32 blockZ, u8 utX, u8 utZ) {
+ s32 res = FALSE;
+
+ if ((blockX >= 0) && (blockX < 5) && (blockZ >= 0) && (blockZ < 6) && (utX < 0x10) && (utZ < 0x10)) {
+ u16 item = common_data.foreground[blockZ][blockX].items[utZ][utX];
+
+ if ((item >= 0x5810) && (item < 0x5825)) {
+ res = TRUE;
+ }
+ }
+ return res;
+}
+
+void mNpc_SetReturnAnimal(Animal_c* returnAnimal) {
+ Anmhome_c* homeInfo;
+ Animal_c* foundAnimal = NULL;
+ u8* nowMax = &common_data.nowNpcMax;
+ Animal_c* animal;
+ s32 foundAnimalIdx;
+
+ if (mLd_PlayerManKindCheck() == FALSE && mNpc_CheckFreeAnimalInfo(returnAnimal) == FALSE) {
+ if (returnAnimal->isMoving == 0) {
+ animal = common_data.animals;
+ foundAnimalIdx = mNpc_SearchAnimalinfo(animal, returnAnimal->id.npcId, ANIMAL_NUM_MAX);
+ if (foundAnimalIdx != -1) {
+ foundAnimal = &animal[foundAnimalIdx];
+ mNpc_DestroyHouse(&foundAnimal->homeInfo);
+ (*nowMax)--;
+ if (common_data.removeAnimalIdx == foundAnimalIdx) {
+ common_data.removeAnimalIdx = 0xFF;
+ }
+ } else if ((*nowMax) >= ANIMAL_NUM_MAX) {
+ foundAnimalIdx = mNpc_GetGoodbyAnimalIdx();
+ foundAnimal = &animal[foundAnimalIdx];
+ mNpc_SetGoodbyAnimalMail(&l_mnpc_goodby_mail, foundAnimal);
+ mNpc_DestroyHouse(&foundAnimal->homeInfo);
+ (*nowMax)--;
+ if (foundAnimalIdx == common_data.removeAnimalIdx) {
+ common_data.removeAnimalIdx = 0xFF;
+ }
+ } else {
+ foundAnimalIdx = mNpc_GetFreeAnimalInfo(animal, ANIMAL_NUM_MAX);
+ if (foundAnimalIdx != -1) {
+ foundAnimal = &animal[foundAnimalIdx];
+ }
+ }
+
+ if (foundAnimal != NULL) {
+ homeInfo = &foundAnimal->homeInfo;
+ mNpc_ClearAnimalInfo(foundAnimal);
+ mNpc_CopyAnimalInfo(foundAnimal, returnAnimal);
+ if (mNpc_CheckBuildHouse(foundAnimal->homeInfo.blockX - 1, foundAnimal->homeInfo.blockZ - 1,
+ foundAnimal->homeInfo.utX, foundAnimal->homeInfo.utZ - 1) == TRUE) {
+ mNpc_BuildHouseBeforeFieldct(foundAnimal->id.npcId, homeInfo->blockX - 1, homeInfo->blockZ - 1,
+ homeInfo->utX, homeInfo->utZ - 1);
+ } else {
+ homeInfo->blockX = 0xFF;
+ homeInfo->blockZ = 0xFF;
+ homeInfo->utX = 0xFF;
+ homeInfo->utZ = 0xFF;
+ }
+ (*nowMax)++;
+ if ((*nowMax) > ANIMAL_NUM_MAX) {
+ (*nowMax) = ANIMAL_NUM_MAX;
+ }
+ }
+ } else {
+ mNpc_CopyAnimalPersonalID(&common_data.lastRemovedAnimalId, &returnAnimal->id);
+ }
+ mNpc_ClearAnimalInfo(returnAnimal);
+ }
+}
+
+void mNpc_AddActor_inBlock(FieldMakeMoveActor* moveActor, u8 bx, u8 bz) {
+ mNpc_AddNpc_inNpcRoom(moveActor, bx, bz);
+}
+
+void mNpc_SetNpcNameID(Animal_c* animal, s32 count) {
+ s32 i;
+
+ for (i = 0; i < count; i++) {
+ if (animal != NULL) {
+ if (ACTOR_FGNAME_GET_F000(animal->id.npcId) == FGNAME_F000_E) {
+ animal->id.nameId = animal->id.npcId & 0xFF;
+ }
+ }
+ animal++;
+ }
+}
+
+void mNpc_LoadNpcNameString(char* name, u8 npcId) {
+ char npcName[ANIMAL_NAME_LEN];
+ s32 offset;
+
+ if (npcId < 0xFF) {
+ offset = npcId * ANIMAL_NAME_LEN;
+ DmaMgr_RequestSyncDebug(npcName, (offset + 8) + SEGMENT_ROM_START(segment_00E04000), 8, "../m_npc.c", 0x1916);
+ mem_copy((u8*)name, (u8*)npcName, ANIMAL_NAME_LEN);
+ }
+}
+
+void mNpc_GetNpcWorldNameTableNo(char* name, u16 npcId) {
+ char* worldName = l_no_name_npc_name;
+ char npcName[PLAYER_NAME_LEN];
+
+ if (name != NULL) {
+ u8 id = npcId & 0xFF;
+
+ if ((ACTOR_FGNAME_GET_F000(npcId) == FGNAME_F000_E) && (id < 0xFF)) {
+ mNpc_LoadNpcNameString(npcName, id);
+ worldName = npcName;
+ }
+ }
+ mPr_CopyPlayerName(name, worldName);
+}
+
+void mNpc_GetNpcWorldNameAnm(char* name, AnmPersonalID_c* anmId) {
+ char* worldName = l_no_name_npc_name;
+ char npcName[PLAYER_NAME_LEN];
+
+ if (anmId != NULL) {
+ if (ACTOR_FGNAME_GET_F000(anmId->npcId) == FGNAME_F000_E) {
+ mNpc_GetNpcWorldNameTableNo(npcName, anmId->npcId);
+ worldName = npcName;
+ }
+ }
+ mPr_CopyPlayerName(name, worldName);
+}
+
+void mNpc_GetNpcWorldNameP(char* name, u16 npcId) {
+ s32 i;
+ SpecialNpcData* sp = l_sp_actor_name;
+ char* worldName = l_no_name_npc_name;
+
+ for (i = 0; i < ARRAY_COUNT(l_sp_actor_name); i++) {
+ if (npcId == sp->specialNpcId) {
+ mString_Load_StringFromRom(load_name, PLAYER_NAME_LEN, sp->nameStringNumber);
+ worldName = load_name;
+ break;
+ }
+ sp++;
+ }
+ mPr_CopyPlayerName(name, worldName);
+}
+
+void mNpc_GetNpcWorldName(char* name, Npc* npc) {
+ char* worldName = l_no_name_npc_name;
+ char npcName[PLAYER_NAME_LEN];
+
+ if ((name != NULL) && (npc != NULL)) {
+ if (npc->actor.part == ACTOR_PART_NPC) {
+ if (npc->npcInfo.animal != NULL) {
+ mNpc_GetNpcWorldNameAnm(npcName, &npc->npcInfo.animal->id);
+ } else {
+ mNpc_GetNpcWorldNameP(npcName, npc->actor.fgName);
+ }
+ } else {
+ mNpc_GetNpcWorldNameP(npcName, npc->actor.fgName);
+ }
+ worldName = npcName;
+ }
+ mPr_CopyPlayerName(name, worldName);
+}
+
+void mNpc_GetRandomAnimalName(char* dst) {
+ Animal_c* animal = common_data.animals;
+ u16 bitfield = 0;
+ s32 num = 0;
+ s32 select;
+ s32 i;
+
+ if (dst != NULL) {
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (mNpc_CheckFreeAnimalInfo(animal) == FALSE) {
+ num++;
+ bitfield |= (1 << i);
+ }
+ animal++;
+ }
+
+ if (num > 0) {
+ animal = common_data.animals;
+ select = RANDOM(num);
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (((bitfield >> i) & 1) == 1) {
+ if (select == 0) {
+ mNpc_GetNpcWorldNameAnm(dst, &animal->id);
+ break;
+ } else {
+ select--;
+ }
+ }
+ animal++;
+ }
+ }
+ }
+}
+
+void mNpc_GetAnimalPlateName(char* dst, xyz_t wpos) {
+ UNUSED s32 pad;
+ Animal_c* animal = common_data.animals;
+ s32 bx;
+ s32 bz;
+ s32 utX;
+ s32 utZ;
+ s32 i;
+ Anmhome_c* home;
+
+ if (mFI_Wpos2BkandUtNuminBlock(&bx, &bz, &utX, &utZ, wpos) == TRUE) {
+
+ utX++;
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (mNpc_CheckFreeAnimalInfo(animal) == FALSE) {
+ home = &animal->homeInfo;
+
+ if (home->blockX == bx && home->blockZ == bz && home->utX == utX && home->utZ == utZ) {
+ mNpc_GetNpcWorldNameAnm(dst, &animal->id);
+ break;
+ }
+ }
+
+ animal++;
+ }
+ }
+}
+
+NpcLooks mNpc_GetNpcLooks(Actor* actor) {
+ NpcLooks looks = NPC_LOOKS_BOY;
+
+ if (actor != NULL && actor->part == ACTOR_PART_NPC) {
+ Npc* npc = (Npc*)actor;
+
+ if (npc->npcInfo.animal != NULL) {
+ looks = npc->npcInfo.animal->id.looks;
+ }
+ }
+
+ return looks;
+}
+
+NpcSex mNpc_GetActorSex(u16 npcId) {
+ SpecialNpcData* spInfo = l_sp_actor_name;
+ NpcSex sex = NPC_SEX_MALE;
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(l_sp_actor_name); i++) {
+ if (npcId == spInfo->specialNpcId) {
+ sex = spInfo->sex;
+ break;
+ }
+
+ spInfo++;
+ }
+
+ return sex;
+}
+
+NpcSex mNpc_GetLooks2Sex(NpcLooks looks) {
+ NpcSex sex = NPC_SEX_OTHER;
+
+ if (looks == NPC_LOOKS_GIRL || looks == NPC_LOOKS_KO_GIRL || looks == NPC_LOOKS_NANIWA_LADY) {
+ sex = NPC_SEX_FEMALE;
+ } else if (looks == NPC_LOOKS_BOY || looks == NPC_LOOKS_SPORT_MAN || looks == NPC_LOOKS_GRIM_MAN) {
+ sex = NPC_SEX_MALE;
+ }
+
+ return sex;
+}
+
+NpcSex mNpc_GetAnimalSex(Animal_c* animal) {
+ NpcSex sex = NPC_SEX_OTHER;
+
+ if (animal != NULL) {
+ sex = mNpc_GetLooks2Sex(animal->id.looks);
+ }
+
+ return sex;
+}
+
+NpcSex mNpc_GetNpcSex(Actor* actor) {
+ NpcSex sex;
+
+ if (actor != NULL && actor->part == ACTOR_PART_NPC) {
+ Npc* npc = (Npc*)actor;
+
+ sex = mNpc_GetAnimalSex(npc->npcInfo.animal);
+ } else {
+ sex = mNpc_GetActorSex(actor->fgName);
+ }
+
+ return sex;
+}
+
+s32 mNpc_GetNpcSoundSpecNotAnimal(u16 npcId) {
+ SpecialNpcData* spInfo = l_sp_actor_name;
+ s32 soundSpec = 2;
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(l_sp_actor_name); i++) {
+ if (npcId == spInfo->specialNpcId) {
+ soundSpec = spInfo->soundId;
+ break;
+ }
+
+ spInfo++;
+ }
+
+ return soundSpec;
+}
+
+s32 mNpc_GetNpcSoundSpec(Actor* actor) {
+ static s32 spec_table[NPC_LOOKS_NUM] = { 4, 4, 2, 2, 3, 4 };
+
+ s32 soundSpec = 2;
+ u8 looks;
+
+ if (actor != NULL) {
+ if (actor->part == ACTOR_PART_NPC) {
+ Npc* npc = (Npc*)actor;
+
+ if (npc->npcInfo.animal != NULL) {
+ looks = npc->npcInfo.animal->id.looks;
+
+ if (looks >= NPC_LOOKS_NUM) {
+ looks = NPC_LOOKS_BOY;
+ }
+
+ soundSpec = spec_table[looks];
+ } else {
+ soundSpec = mNpc_GetNpcSoundSpecNotAnimal(actor->fgName);
+ }
+ } else {
+ soundSpec = mNpc_GetNpcSoundSpecNotAnimal(actor->fgName);
+ }
+ }
+
+ return soundSpec;
+}
+
+void mNpc_GetMsg(UNUSED s32 arg) {
+}
+
+void mNpc_InitNpcAllInfo(s32 mallocFlag) {
+ common_data.nowNpcMax = NPC_LOOKS_NUM;
+ common_data.removeAnimalIdx = 0xFF;
+ mNpc_ClearAnimalPersonalID(&common_data.lastRemovedAnimalId);
+ mNpc_ClearAnyAnimalInfo(common_data.animals, ANIMAL_NUM_MAX);
+ mNpc_DecideLivingNpcMax(common_data.animals, NPC_LOOKS_NUM, mallocFlag);
+ mNpc_SetNpcNameID(common_data.animals, ANIMAL_NUM_MAX);
+}
+
+s32 mNpc_CheckGrowFieldRank() {
+ static s32 npc_grow_prob[7] = { 40, 50, 60, 70, 80, 90, 100 };
+
+ s32 rank = mFAs_GetFieldRank();
+ UNUSED s32 pad;
+ s32 res = FALSE;
+
+ if (rank >= 0 && rank < 7) {
+ if (RANDOM(100) < npc_grow_prob[rank]) {
+ res = TRUE;
+ }
+ }
+
+ return res;
+}
+
+s32 mNpc_CheckGrow() {
+ UNUSED s32 pad;
+ lbRTC_time_c* rtcTime = &common_data.time.rtcTime;
+ lbRTC_time_c* lastGrowTime = &common_data.lastGrowTime;
+ s32 res = FALSE;
+
+ if (common_data.nowNpcMax < ANIMAL_NUM_MAX) {
+ if (lbRTC_IsEqualTime(&mTM_rtcTime_clear_code, lastGrowTime, lbRTC_CHECK_ALL) == TRUE) {
+ lbRTC_TimeCopy(lastGrowTime, rtcTime);
+ } else if (mNpc_CheckGrowFieldRank() == TRUE) {
+ u32 interval;
+
+ if (lbRTC_IsOverTime(lastGrowTime, rtcTime) == lbRTC_OVER) {
+ interval = lbRTC_IntervalTime(rtcTime, lastGrowTime);
+ } else {
+ interval = lbRTC_IntervalTime(lastGrowTime, rtcTime);
+ }
+
+ if (interval >= (lbRTC_HOURS_PER_DAY * lbRTC_MINUTES_PER_HOUR) && mLd_PlayerManKindCheck() == FALSE &&
+ mNpc_CheckFriendAllAnimal(&common_data.privateInfo->playerId) == TRUE) {
+ res = TRUE;
+ }
+ }
+ }
+
+ return res;
+}
+
+u8 mNpc_GetMinLooks(u8* bitfield, s32* minLooksNum) {
+ s32 minLooksAnimal = ANIMAL_NUM_MAX;
+ u8 minLooks = NPC_LOOKS_NUM;
+ u8 i;
+
+ bitfield[0] = 0;
+ minLooksNum[0] = 0;
+
+ for (i = 0; i < NPC_LOOKS_NUM; i++) {
+ s32 notAppearedNum = mNpc_GetLooks2NotHaveAppearedNum(i);
+
+ if (notAppearedNum > 0) {
+ s32 sameLooksNum = mNpc_GetSameLooksNum(i);
+
+ if (minLooksAnimal > sameLooksNum) {
+ minLooksAnimal = sameLooksNum;
+ minLooks = i;
+ bitfield[0] = 0;
+ bitfield[0] |= (1 << i);
+ minLooksNum[0] = 1;
+ } else if (minLooksAnimal == sameLooksNum) {
+ bitfield[0] |= (1 << i);
+ minLooksNum[0]++;
+ }
+ }
+ }
+
+ if (bitfield[0] == 0 && minLooksNum[0] == 0) {
+ mNpc_ResetHaveAppeared_common(common_data.npcUsedTable, common_data.animals);
+
+ for (i = 0; i < NPC_LOOKS_NUM; i++) {
+ bitfield[0] |= (1 << i);
+ minLooksNum[0]++;
+ }
+ }
+
+ if (minLooksNum[0] > 1) {
+ minLooks = NPC_LOOKS_NUM;
+ }
+
+ return minLooks;
+}
+
+NpcSex mNpc_GetMinSex() {
+ Animal_c* animal = common_data.animals;
+ s32 males = 0;
+ s32 females = 0;
+ NpcSex res;
+ s32 i;
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (mNpc_CheckFreeAnimalInfo(animal) == FALSE) {
+ switch (mNpc_GetAnimalSex(animal)) {
+ case NPC_SEX_MALE:
+ males++;
+ break;
+ case NPC_SEX_FEMALE:
+ females++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ animal++;
+ }
+
+ if (females < males) {
+ res = NPC_SEX_MALE;
+ } else {
+ res = NPC_SEX_FEMALE;
+ }
+
+ return res;
+}
+
+s32 mNpc_GrowLooksNpcIdx(u8 looks) {
+ u8* looks_table = npc_looks_table;
+ s32 npc_idx;
+ s32 candidates;
+ s32 res;
+ s32 i;
+ s32 j;
+ s32 selected;
+
+ candidates = 0;
+ res = -1;
+ npc_idx = 0;
+
+ if (looks < NPC_LOOKS_NUM) {
+ bzero(candidate_table, sizeof(candidate_table));
+
+ for (i = 0; i < ARRAY_COUNT(candidate_table); i++) {
+ for (j = 0; j < 8; j++) {
+ if (looks == *looks_table) {
+ if ((mNpc_SearchAnimalinfo(common_data.animals, ((i * 8) + j) | 0xE000, ANIMAL_NUM_MAX) == -1) &&
+ (mNpc_GetHaveAppeared_idx(npc_idx) == FALSE)) {
+ candidates++;
+ candidate_table[i] |= 1 << j;
+ }
+ }
+
+ npc_idx++;
+ looks_table++;
+
+ if (npc_idx >= NPC_NUM) {
+ break;
+ }
+ }
+
+ if (npc_idx >= NPC_NUM) {
+ break;
+ }
+ }
+ }
+
+ if (candidates > 0) {
+ selected = RANDOM(candidates);
+ npc_idx = 0;
+
+ for (i = 0; i < ARRAY_COUNT(candidate_table); i++) {
+ if (npc_idx >= NPC_NUM) {
+ break;
+ }
+
+ for (j = 0; j < 8; j++) {
+ if (npc_idx >= NPC_NUM) {
+ break;
+ }
+
+ if (((candidate_table[i] >> j) & 1) == 1) {
+ if (selected <= 0) {
+ res = npc_idx;
+ break;
+ } else {
+ selected--;
+ }
+ }
+
+ npc_idx++;
+ }
+
+ if (res != -1) {
+ break;
+ }
+ }
+ }
+
+ return res;
+}
+
+void mNpc_SetAnimalInfoNpcIdx(Animal_c* animal, s32 idx) {
+ u32 offset;
+
+ if (idx >= 0 && idx < NPC_NUM) {
+ offset = idx * 6;
+ DmaMgr_RequestSyncDebug(&npc_def_list, (offset + SEGMENT_ROM_START(segment_00E03000)), 8, "../m_npc.c", 0x1CB3);
+ mNpc_SetDefAnimalInfo(animal, idx | 0xE000, npc_looks_table[idx], &npc_def_list);
+ }
+}
+
+s32 mNpc_SetGrowNpc(u8 looks) {
+ Animal_c* animal = common_data.animals;
+ UNUSED s32 pad;
+ s32 idx;
+ s32 npcIdx;
+
+ idx = mNpc_UseFreeAnimalInfo(animal, ANIMAL_NUM_MAX);
+ if (idx != -1) {
+ animal += idx;
+ npcIdx = mNpc_GrowLooksNpcIdx(looks);
+
+ if (npcIdx != -1) {
+ mNpc_SetAnimalInfoNpcIdx(animal, npcIdx);
+ animal->movedIn = TRUE;
+ } else {
+ idx = -1;
+ }
+ }
+
+ return idx;
+}
+
+void mNpc_Grow() {
+ u8 minLooks;
+ u8 minLooksBitfield;
+ s32 minLooksNum;
+ u8 bitfieldSave;
+ s32 looksSave;
+ NpcSex minSex;
+ s32 selected;
+ s32 growIdx;
+ u8 looks;
+
+ if (mNpc_CheckGrow() == TRUE) {
+ mNpc_ResetHaveAppeared();
+ lbRTC_TimeCopy(&common_data.lastGrowTime, &common_data.time.rtcTime);
+
+ minLooks = mNpc_GetMinLooks(&minLooksBitfield, &minLooksNum);
+
+ /* Multiple personalities are tied for minimum */
+ if (minLooks == NPC_LOOKS_NUM) {
+ minSex = mNpc_GetMinSex();
+ if (minSex != NPC_SEX_OTHER) {
+ bitfieldSave = minLooksBitfield;
+ looksSave = minLooksNum;
+
+ /* Clear any tied minimum personalities which are of the greater sex */
+ for (looks = 0; looks < NPC_LOOKS_NUM; looks++) {
+ if (((minLooksBitfield >> looks) & 1) == 1 && mNpc_GetLooks2Sex(looks) != minSex) {
+ minLooksBitfield &= ~(1 << looks);
+ minLooksNum--;
+ }
+ }
+
+ if (minLooksNum == 0 || minLooksNum == looksSave) {
+ /* Either all personalities were cleared or none were, so restore the prior state */
+ minLooksBitfield = bitfieldSave;
+ minLooksNum = looksSave;
+ }
+ }
+
+ selected = RANDOM(minLooksNum);
+
+ for (looks = 0; looks < NPC_LOOKS_NUM; looks++) {
+ if (((minLooksBitfield >> looks) & 1) == 1) {
+ if (selected <= 0) {
+ minLooks = looks;
+ break;
+ } else {
+ selected--;
+ }
+ }
+ }
+ }
+
+ growIdx = mNpc_SetGrowNpc(minLooks);
+
+ if (growIdx >= 0 && growIdx < ANIMAL_NUM_MAX) {
+ mNpc_SetNpcNameID(&common_data.animals[growIdx], 1);
+ mNpc_AddNowNpcMax(&common_data.nowNpcMax);
+ }
+ }
+}
+
+s32 mNpc_CheckNpcSet_fgcol(u16 arg0, u32 arg1) {
+ s32 res = FALSE;
+
+ if (func_8008D7B0_jp(arg0)) {
+ res = func_8007244C_jp(arg1);
+ }
+
+ return res;
+}
+
+s32 mNpc_CheckNpcSet_fgcol_hard(u16 arg0, u32 arg1) {
+ s32 res = FALSE;
+
+ if (func_8008D7B0_jp(arg0) && (arg1 <= 2 || (arg1 >= 4 && arg1 <= 6) || arg1 == 7)) {
+ res = TRUE;
+ }
+
+ return res;
+}
+
+s32 mNpc_CheckNpcSet(s32 bx, s32 bz, s32 ut_x, s32 ut_z) {
+ mCoBG_unkStructUnion* collision = mFI_GetBkNum2ColTop(bx, bz);
+ u16* items = mFI_BkNumtoUtFGTop(bx, bz);
+ s32 res = FALSE;
+
+ if (collision != NULL && items != NULL) {
+ res = mNpc_CheckNpcSet_fgcol(items[ut_z * UT_X_NUM + ut_x], collision[ut_z * UT_X_NUM + ut_x].data.unk6);
+ }
+
+ return res;
+}
+
+s32 mNpc_GetMakeUtNuminBlock_hard_area(s32* utX, s32* utZ, s32 bx, s32 bz, s32 restrictArea) {
+ mCoBG_unkStructUnion* col;
+ u16* items;
+ s32 nowUtX;
+ s32 nowUtZ;
+ s32 minUtX;
+ s32 minUtZ;
+ s32 idx;
+ s32 res;
+ s32 i;
+ s32 j;
+
+ col = mFI_GetBkNum2ColTop(bx, bz);
+ items = mFI_BkNumtoUtFGTop(bx, bz);
+ minUtX = UT_X_NUM;
+ minUtZ = UT_Z_NUM;
+ res = FALSE;
+
+ if (restrictArea < 0 || restrictArea > 9) {
+ return FALSE;
+ }
+
+ if (items != NULL && col != NULL) {
+ for (i = restrictArea; i < UT_Z_NUM - restrictArea; i++) {
+ for (j = restrictArea; j < UT_X_NUM - restrictArea; j++) {
+ idx = i * UT_X_NUM + j;
+ if (mNpc_CheckNpcSet_fgcol_hard(items[idx], col[idx].data.unk6) == TRUE) {
+ if (col[idx].data.unk1 == col[idx].data.unk2 && col[idx].data.unk1 == col[idx].data.unk3 &&
+ col[idx].data.unk1 == col[idx].data.unk4 && col[idx].data.unk1 == col[idx].data.unk5) {
+ nowUtX = 8 - j;
+ nowUtZ = 8 - i;
+
+ nowUtX = ABS(nowUtX);
+ nowUtZ = ABS(nowUtZ);
+
+ if (minUtX > nowUtX && minUtZ > nowUtZ) {
+ *utX = j;
+ *utZ = i;
+ minUtX = nowUtX;
+ minUtZ = nowUtZ;
+ res = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return res;
+}
+
+s32 mNpc_GetMakeUtNuminBlock_area(s32* utX, s32* utZ, s32 bx, s32 bz, s32 restrictArea) {
+ s32 candidates;
+ mCoBG_unkStructUnion* col;
+ u16* fgTop;
+ s32 i;
+ s32 j;
+ s32 rand;
+ s32 res;
+
+ u16* fgPtr = fg_flag;
+
+ col = mFI_GetBkNum2ColTop(bx, bz);
+ fgTop = mFI_BkNumtoUtFGTop(bx, bz);
+ candidates = 0;
+ res = FALSE;
+
+ if (restrictArea < 0 || restrictArea > 9) {
+ return FALSE;
+ }
+
+ bzero(fg_flag, sizeof(fg_flag));
+
+ if (fgTop != NULL && col != NULL) {
+ for (i = restrictArea; i < UT_Z_NUM - restrictArea; i++) {
+ for (j = restrictArea; j < UT_X_NUM - restrictArea; j++) {
+ if (mNpc_CheckNpcSet_fgcol(fgTop[i * UT_X_NUM + j], col[i * UT_X_NUM + j].data.unk6) == TRUE) {
+ *fgPtr |= 1 << j;
+ candidates++;
+ }
+ }
+
+ fgPtr++;
+ }
+ }
+
+ fgPtr = fg_flag;
+ if (candidates > 0) {
+ rand = RANDOM(candidates);
+
+ for (i = restrictArea; i < UT_Z_NUM - restrictArea; i++) {
+ for (j = restrictArea; j < UT_X_NUM - restrictArea; j++) {
+ if (((*fgPtr >> j) & 1) == 1) {
+ if (rand == 0) {
+ *utX = j;
+ *utZ = i;
+ res = TRUE;
+
+ break;
+ } else {
+ rand--;
+ }
+ }
+ }
+
+ if (res == TRUE) {
+ break;
+ }
+
+ fgPtr++;
+ }
+ }
+
+ return res;
+}
+
+s32 mNpc_GetMakeUtNuminBlock(s32* utX, s32* utZ, s32 bx, s32 bz) {
+ return mNpc_GetMakeUtNuminBlock_area(utX, utZ, bx, bz, 1);
+}
+
+void mNpc_ClearTalkInfo() {
+ NpcTalkInfo* talkInfo = l_npc_talk_info;
+ s32 i;
+
+ bzero(talkInfo, sizeof(l_npc_talk_info));
+
+ for (i = 0; i < ARRAY_COUNT(l_npc_talk_info); i++) {
+ talkInfo->questRequest = TRUE;
+ talkInfo++;
+ }
+}
+
+void mNpc_TimerCountDown(NpcTalkInfo* talkInfo) {
+ if (talkInfo->timer > 0) {
+ talkInfo->timer--;
+ }
+}
+
+NpcTemper l_npc_temper[NPC_FEEL_NUM] = { { 4000, 12, 15 }, { 3000, 10, 13 }, { 4000, 12, 15 },
+ { 4000, 10, 13 }, { 5000, 9, 12 }, { 5000, 9, 12 } };
+
+void mNpc_SetUnlockTimer(u16* unlockTimer, u16* resetTimer, s32 feel) {
+ unlockTimer[0] = l_npc_temper[feel].unlockTimer;
+ resetTimer[0] = unlockTimer[0];
+}
+
+s32 mNpc_CountTalkNum(s32 animalIdx, s32 feel) {
+ s32 res = FALSE;
+
+ if (animalIdx != -1) {
+ NpcTalkInfo* talkInfo = &l_npc_talk_info[animalIdx];
+
+ if (talkInfo->talkNum < l_npc_temper[feel].talkNumMax && talkInfo->timer > 0) {
+ talkInfo->talkNum++;
+ res = TRUE;
+ }
+ }
+
+ return res;
+}
+
+s32 mNpc_CheckOverImpatient(s32 animalIdx, s32 feel) {
+ s32 res = FALSE;
+
+ if (animalIdx != -1) {
+ NpcTalkInfo* talkInfo = &l_npc_talk_info[animalIdx];
+
+ if (talkInfo->talkNum >= l_npc_temper[feel].overImpatientNum) {
+ res = TRUE;
+ }
+ }
+
+ return res;
+}
+
+s32 mNpc_GetOverImpatient(s32 animalIdx, s32 feel) {
+ s32 patience = NPC_PATIENCE_NORMAL;
+
+ if (animalIdx != -1) {
+ NpcTalkInfo* talkInfo = &l_npc_talk_info[animalIdx];
+
+ if (talkInfo->talkNum >= l_npc_temper[feel].overImpatientNum) {
+ if (talkInfo->talkNum >= l_npc_temper[feel].talkNumMax) {
+ patience = NPC_PATIENCE_ANNOYED;
+ } else {
+ patience = NPC_PATIENCE_MILDLY_ANNOYED;
+ }
+ }
+ }
+
+ return patience;
+}
+
+s32 mNpc_CheckQuestRequest(s32 animalIdx) {
+ s32 res = FALSE;
+
+ if (animalIdx != -1) {
+ NpcTalkInfo* talkInfo = &l_npc_talk_info[animalIdx];
+
+ if (talkInfo->questRequest == TRUE) {
+ res = TRUE;
+ }
+ }
+
+ return res;
+}
+
+void mNpc_SetQuestRequestOFF(s32 animalIdx, s32 feel) {
+ NpcTalkInfo* talkInfo = &l_npc_talk_info[animalIdx];
+
+ if (animalIdx >= 0 && animalIdx < ARRAY_COUNT(l_npc_talk_info)) {
+ if (talkInfo->questRequest == TRUE) {
+ mNpc_SetUnlockTimer(&talkInfo->unlockTimer, &talkInfo->resetTimer, feel);
+ }
+
+ talkInfo->questRequest = FALSE;
+ }
+}
+
+void mNpc_UnlockTimerCountDown(NpcTalkInfo* talkInfo) {
+ if (talkInfo != NULL && talkInfo->unlockTimer > 0 && talkInfo->unlockTimer > (talkInfo->resetTimer - 1000)) {
+ talkInfo->unlockTimer--;
+ }
+}
+
+void mNpc_TalkInfoMove() {
+ NpcTalkInfo* talkInfo = l_npc_talk_info;
+ s32 i;
+
+ if (mFI_CheckPlayerWade(1) == TRUE) {
+ for (i = 0; i < ARRAY_COUNT(l_npc_talk_info); i++) {
+ talkInfo->resetTimer = talkInfo->unlockTimer;
+ talkInfo++;
+ }
+ }
+
+ talkInfo = l_npc_talk_info;
+ for (i = 0; i < ARRAY_COUNT(l_npc_talk_info); i++) {
+ mNpc_TimerCountDown(talkInfo);
+ mNpc_UnlockTimerCountDown(talkInfo);
+
+ if (talkInfo->unlockTimer == 0 && talkInfo->resetTimer != 0) {
+ talkInfo->talkNum = 0;
+ talkInfo->questRequest = TRUE;
+ talkInfo->resetTimer = 0;
+ }
+
+ talkInfo++;
+ }
+}
+
+void mNpc_TalkEndMove(s32 animalIdx, s32 feel) {
+ UNUSED s32 pad;
+ if (animalIdx >= 0 && animalIdx < ARRAY_COUNT(l_npc_talk_info) && feel >= 0 && feel < NPC_FEEL_NUM) {
+ NpcTalkInfo* talkInfo = &l_npc_talk_info[animalIdx];
+ talkInfo->timer = 1000;
+
+ if (mNpc_CountTalkNum(animalIdx, feel) == TRUE && mNpc_CheckOverImpatient(animalIdx, feel) == TRUE) {
+ mNpc_SetUnlockTimer(&talkInfo->unlockTimer, &talkInfo->resetTimer, feel);
+ }
+ }
+}
+
+s32 mNpc_GetNpcFloorNo() {
+ u16 field_id = mFI_GetFieldId();
+ u16 owner_name = common_data.houseOwnerName;
+ s32 floor_no = -1;
+
+ if (((field_id & 0xF000) == 0x4000) && (owner_name != 0) && (owner_name != 0xFFFF)) {
+ s32 idx = mNpc_SearchAnimalinfo(common_data.animals, owner_name, ANIMAL_NUM_MAX);
+
+ floor_no = common_data.npclist[idx].houseData.floorId;
+ }
+
+ return floor_no;
+}
+
+void mNpc_SetTalkBee() {
+ if (common_data.beeStingFlag != TRUE) {
+ Animal_c* animal = common_data.animals;
+ NpcList* npclist = common_data.npclist;
+ s32 i;
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (mNpc_CheckFreeAnimalInfo(animal) == FALSE) {
+ npclist->flags.beeSting = TRUE;
+ }
+
+ animal++;
+ npclist++;
+ }
+ }
+}
+
+u8 mNpc_GetFishCompleteTalk(NpcList* npclist) {
+ u8 res = TRUE;
+
+ if (npclist != NULL) {
+ res = npclist->flags.fishComplete;
+ }
+
+ return res;
+}
+
+u8 mNpc_GetInsectCompleteTalk(NpcList* npclist) {
+ u8 res = TRUE;
+
+ if (npclist != NULL) {
+ res = npclist->flags.insectComplete;
+ }
+
+ return res;
+}
+
+void mNpc_SetFishCompleteTalk(NpcList* npclist) {
+ if (npclist != NULL) {
+ npclist->flags.fishComplete = TRUE;
+ }
+}
+
+void mNpc_SetInsectCompleteTalk(NpcList* npclist) {
+ if (npclist != NULL) {
+ npclist->flags.insectComplete = TRUE;
+ }
+}
+
+void mNpc_SetNpcHomeYpos() {
+ Animal_c* animal = common_data.animals;
+ NpcList* npclist = common_data.npclist;
+ s32 i;
+
+ for (i = 0; i < ANIMAL_NUM_MAX; i++) {
+ if (mNpc_CheckFreeAnimalInfo(animal) == FALSE) {
+ npclist->homePosition.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(npclist->homePosition, 0.0f);
+ }
+
+ animal++;
+ npclist++;
+ }
+}
+
+void mNpc_PrintRemoveInfo(gfxprint* gfxprint) {
+ Animal_c* remove_anm = NULL;
+ Animal_c* in_anm = mNpc_GetInAnimalP();
+ u8 removeAnimalIdx = common_data.removeAnimalIdx;
+
+ gfxprint_color(gfxprint, 200, 150, 50, 255);
+ gfxprint_locate8x8(gfxprint, 3, 10);
+
+ if (removeAnimalIdx < ANIMAL_NUM_MAX) {
+ remove_anm = &common_data.animals[removeAnimalIdx];
+ }
+
+ if (remove_anm != NULL) {
+ if (in_anm != NULL) {
+ gfxprint_printf(gfxprint, "%4x %3d %3d", removeAnimalIdx, remove_anm->id.nameId, in_anm->id.nameId);
+ } else {
+ gfxprint_printf(gfxprint, "%4x %3d ---", removeAnimalIdx, remove_anm->id.nameId);
+ }
+ } else if (in_anm != NULL) {
+ gfxprint_printf(gfxprint, "%4x --- %3d", removeAnimalIdx, in_anm->id.nameId);
+ } else {
+ gfxprint_printf(gfxprint, "%4x --- ---", removeAnimalIdx);
+ }
+}
+
+s32 l_mnpc_animal_idx = -1;
+
+void mNpc_SetTalkAnimalIdx_fdebug(AnmPersonalID_c* anm_id) {
+ if (anm_id != NULL) {
+ l_mnpc_animal_idx = mNpc_SearchAnimalPersonalID(anm_id);
+ }
+}
+
+void mNpc_PrintFriendship_fdebug(gfxprint* gfxprint) {
+ Anmmem_c* memory;
+ PrivateInfo* priv;
+ int x = 3;
+ int y = 19;
+ int i;
+
+ if (l_mnpc_animal_idx >= 0 && l_mnpc_animal_idx < ANIMAL_NUM_MAX) {
+ memory = common_data.animals[l_mnpc_animal_idx].memories;
+
+ if (memory != NULL) {
+ gfxprint_color(gfxprint, 250, 100, 170, 255);
+ gfxprint_locate8x8(gfxprint, 3, 18);
+ priv = common_data.privateInfo;
+
+ if (priv != NULL) {
+ gfxprint_printf(gfxprint, "%4x ", priv->playerId.playerId);
+ } else {
+ gfxprint_printf(gfxprint, "**** ");
+ }
+
+ gfxprint_color(gfxprint, 50, 150, 50, 255);
+
+ for (i = 0; i < ANIMAL_MEMORY_NUM; i++) {
+ if (i == 4) {
+ y++;
+ x = 3;
+ }
+
+ gfxprint_locate8x8(gfxprint, x, y);
+ if (mNpc_CheckFreeAnimalMemory(memory) == FALSE) {
+ gfxprint_printf(gfxprint, "%4x %3d ", memory->memoryPlayerId.playerId, memory->friendship);
+ } else {
+ gfxprint_printf(gfxprint, "**** *** ");
+ }
+
+ memory++;
+ x += 9;
+ }
+ }
+ }
+}
diff --git a/src/code/m_npc_walk.c b/src/code/m_npc_walk.c
index 60507ed..e784332 100644
--- a/src/code/m_npc_walk.c
+++ b/src/code/m_npc_walk.c
@@ -407,7 +407,7 @@ void mNpcW_GetBlockXZNumExceptHome(s32* goalBlockX, s32* goalBlockZ, Animal_c* a
s32 mNpcW_CheckDiffBlockWalkNpcHome(s32 blockX, s32 blockZ, NpcWalkInfo* info) {
s32 res = FALSE;
- AnmHome_c* home;
+ Anmhome_c* home;
s32 i;
s32 idx;
@@ -445,7 +445,7 @@ void mNpcW_SetHomeBlockSource(NpcWalking* walk, Animal_c* animal) {
for (i = 0; i < ANIMAL_NUM_MAX; i++) {
if (mNpc_CheckFreeAnimalPersonalID(&animal->id) == FALSE) {
- AnmHome_c* home = &animal->homeInfo;
+ Anmhome_c* home = &animal->homeInfo;
if (mNpcW_CheckDiffBlockWalkNpcHome(home->blockX, home->blockZ, walk->info) == TRUE) {
field |= (1 << i);
@@ -458,7 +458,7 @@ void mNpcW_SetHomeBlockSource(NpcWalking* walk, Animal_c* animal) {
if (num > 0) {
s32 chosen = RANDOM(num);
- AnmHome_c* homeInfo;
+ Anmhome_c* homeInfo;
for (i = 0; i < ANIMAL_NUM_MAX; i++) {
if (((field >> i) & 1) == 1) {
diff --git a/src/code/m_start_data_init.c b/src/code/m_start_data_init.c
index ebd8701..f920741 100644
--- a/src/code/m_start_data_init.c
+++ b/src/code/m_start_data_init.c
@@ -4,15 +4,14 @@
#include "69CB30.h"
#include "6A83A0.h"
#include "6B81C0.h"
-#include "6B8A70.h"
+#include "m_land.h"
#include "6BA500.h"
#include "6C0690.h"
#include "6C97F0.h"
#include "m_npc_schedule.h"
#include "6D9D80.h"
#include "6DA460.h"
-#include "6DB420.h"
-#include "6DE300.h"
+#include "m_quest.h"
#include "6E30B0.h"
#include "6E7AD0.h"
#include "6ECD90.h"
@@ -75,16 +74,16 @@ void decide_fish_location(u8* fish_location) {
void title_game_haniwa_data_init(void) {
s32 i;
- u8 haniwa_buf[HANIWA_MESSAGE_LEN];
+ char haniwa_buf[HANIWA_MESSAGE_LEN];
s32 j;
Haniwa_c* haniwa;
- func_800C3F70_jp(haniwa_buf, HANIWA_MESSAGE_LEN, 0x55C);
+ mString_Load_StringFromRom(haniwa_buf, HANIWA_MESSAGE_LEN, 0x55C);
for (i = 0; i < mHS_HOUSE_NUM; i++) {
haniwa = &common_data.homes[i].haniwa;
- mem_copy(common_data.homes[i].haniwa.message, haniwa_buf, HANIWA_MESSAGE_LEN);
+ mem_copy(common_data.homes[i].haniwa.message, (u8*)haniwa_buf, HANIWA_MESSAGE_LEN);
for (j = 0; j < HANIWA_ITEM_HOLD_NUM; j++) {
haniwa->items[j].item = EMPTY_NO;
@@ -127,7 +126,7 @@ void mSDI_ClearMoneyPlayerHomeStationBlock(void) {
*items = EMPTY_NO;
if (deposit != NULL) {
- func_8008C478_jp(deposit, ut_x, ut_z);
+ mFI_BlockDepositOFF(deposit, ut_x, ut_z);
}
}
@@ -237,7 +236,7 @@ s32 mSDI_StartInitNew(Game* game2, s32 player_no, s32 malloc_flag) {
mSN_snowman_init();
mHS_house_init();
- lbRTC_TimeCopy(&common_data.unk_0F7FC, &mTM_rtcTime_clear_code);
+ lbRTC_TimeCopy(&common_data.lastGrowTime, &mTM_rtcTime_clear_code);
lbRTC_TimeCopy(&common_data.unk_0F89C, &mTM_rtcTime_clear_code);
lbRTC_TimeCopy(&common_data.unk_0F8A4, &mTM_rtcTime_clear_code);
@@ -401,10 +400,10 @@ void mSDI_StartInitAfter(Game* game, s32 renewal_reserve_flag, s32 malloc_flag)
mTM_set_season();
func_80084DA4_jp();
mEv_2nd_init(&game_play->event);
- func_800AD9FC_jp();
+ mNpc_Grow();
func_80096B64_jp();
- func_800AB054_jp();
- func_800AB09C_jp();
+ mNpc_InitNpcData();
+ mNpc_InitNpcList();
mNpc_SetNpcList(common_data.npclist, common_data.animals, ANIMAL_NUM_MAX, malloc_flag);
mNpc_ClearTalkInfo();
if (renewal_reserve_flag == 1) {
@@ -419,7 +418,7 @@ void mSDI_StartInitAfter(Game* game, s32 renewal_reserve_flag, s32 malloc_flag)
common_data.gokiShockedFlag = FALSE;
func_800A6548_jp();
func_800B9B2C_jp();
- func_800A91DC_jp();
+ mNpc_Remail();
mPr_SendForeingerAnimalMail(common_data.privateInfo);
mPr_StartSetCompleteTalkInfo();
mMsm_SendInformationMail();
diff --git a/src/code/m_submenu.c b/src/code/m_submenu.c
index efffce6..53a03a0 100644
--- a/src/code/m_submenu.c
+++ b/src/code/m_submenu.c
@@ -9,7 +9,7 @@
#include "game.h"
#include "sys_math3d.h"
#include "m_scene.h"
-#include "6DE300.h"
+#include "m_quest.h"
#include "6F5550.h"
#include "libc/stddef.h"
#include "attributes.h"
diff --git a/src/overlays/actors/ovl_Npc/ac_npc.h b/src/overlays/actors/ovl_Npc/ac_npc.h
index 25d97c0..81ac120 100644
--- a/src/overlays/actors/ovl_Npc/ac_npc.h
+++ b/src/overlays/actors/ovl_Npc/ac_npc.h
@@ -11,9 +11,15 @@ struct Npc;
typedef void (*NpcActionFunc)(struct Npc*, struct Game_Play*);
+typedef struct NpcActorInfo {
+ /* 0x0 */ struct Animal_c* animal;
+ /* 0x4 */ struct NpcList* list;
+} NpcActorInfo; // size = 0x8
+
typedef struct Npc {
/* 0x000 */ Actor actor;
- /* 0x174 */ UNK_TYPE1 unk_174[0x594];
+ /* 0x174 */ NpcActorInfo npcInfo;
+ /* 0x17C */ UNK_TYPE1 unk_17C[0x58C];
/* 0x708 */ s32 unk_708;
/* 0x70C */ UNK_TYPE1 unk_70C[0x1E4];
/* 0x8F0 */ ClObjPipe collider;
diff --git a/src/overlays/gamestates/ovl_play/m_play.c b/src/overlays/gamestates/ovl_play/m_play.c
index 35c65fc..2c56cdf 100644
--- a/src/overlays/gamestates/ovl_play/m_play.c
+++ b/src/overlays/gamestates/ovl_play/m_play.c
@@ -358,7 +358,7 @@ void play_cleanup(Game* game) {
Actor_info_dt(&game_play->actorInfo, game_play);
mEv_finish(&game_play->event);
- func_800AA124_jp();
+ mNpc_ClearEventNpc();
mSM_submenu_dt(&game_play->submenu);
game_play->unk_1DAC = -1;
mSM_submenu_ovlptr_cleanup(&game_play->submenu);
diff --git a/yamls/jp/code.yaml b/yamls/jp/code.yaml
index 21ae7f6..cc160a9 100644
--- a/yamls/jp/code.yaml
+++ b/yamls/jp/code.yaml
@@ -55,7 +55,7 @@
- [0x6C0E90, asm, code/m_msg_main]
- [0x6C92D0, asm, code/6C92D0]
- [0x6C97F0, asm, code/6C97F0]
- - [0x6CA4B0, asm, code/m_npc]
+ - [0x6CA4B0, c, code/m_npc]
- [0x6D2720, c, code/m_npc_schedule]
- [0x6D2A70, c, code/m_npc_walk]
- [0x6D3CB0, asm, code/800B0010]
@@ -150,6 +150,7 @@
- [0x72B7A0, .data, code/m_lib]
- [0x72B7D0, .data, code/m_lights]
- [0x72B7F0, data, code/72B7F0]
+ - [0x72F1B0, .data, code/m_npc]
- [0x72F610, .data, code/m_npc_schedule]
- [0x72F7D0, .data, code/m_npc_walk]
- [0x72F980, .data, code/m_player_call]
@@ -207,7 +208,7 @@
- [0x73AEE0, .rodata, code/m_lights]
- [0x73AEF0, rodata, code/m_msg_main]
- [0x73AF40, rodata, code/73AF40]
- - [0x73AF50, rodata, code/73AF50]
+ - [0x73AF50, .rodata, code/m_npc]
- [0x73B000, rodata, code/m_olib]
- [0x73B020, rodata, code/m_player_lib]
- [0x73B0F0, rodata, code/73B0F0]
@@ -267,6 +268,7 @@
- { start: 0x73F4D0, type: .bss, vram: 0x80141E10, name: code/m_lights }
- { start: 0x75B600, type: .bss, vram: 0x80141FA0, name: code/m_malloc }
- { start: 0x75B600, type: bss, vram: 0x80141FE0, name: code/80141FE0 }
+ - { start: 0x73F4D0, type: .bss, vram: 0x80142C00, name: code/m_npc }
- { start: 0x73F4D0, type: .bss, vram: 0x801438B0, name: code/m_npc_walk }
- { start: 0x73F4D0, type: .bss, vram: 0x80143900, name: code/m_player_call }
- { start: 0x73F4D0, type: bss, vram: 0x80143910, name: code/80143910 }