From e52e060be75ae509da64ad3a9af321eba69e987a Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Sat, 21 Oct 2023 01:45:37 -0400 Subject: [PATCH] Implement & link m_shop.c --- config/rel_slices.yml | 5 + include/m_collision_bg.h | 1 + include/m_common_data.h | 2 +- include/m_event.h | 5 + include/m_item_debug.h | 41 + include/m_name_table.h | 104 +- include/m_room_type.h | 1 + include/m_shop.h | 145 +- rel/m_fuusen.c | 2 +- rel/m_home.c | 2 +- rel/m_item_debug.c | 206 +++ rel/m_mail.c | 2 +- rel/m_mail_password_check.c | 2 +- rel/m_shop.c | 2761 +++++++++++++++++++++++++++++++++++ rel/m_watch_my_step.c | 2 +- 15 files changed, 3236 insertions(+), 45 deletions(-) create mode 100644 include/m_item_debug.h create mode 100644 rel/m_item_debug.c create mode 100644 rel/m_shop.c diff --git a/config/rel_slices.yml b/config/rel_slices.yml index d6acca58..c129a041 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -212,6 +212,11 @@ m_room_type/mRmTp_FtrItemNo2FtrIdx.c: .text: [0x803E7878, 0x803E78BC] m_scene_ftr.c: .text: [0x803E7998, 0x803E7A7C] +m_shop.c: + .text: [0x803E7A7C, 0x803EC240] + .rodata: [0x80643270, 0x806432D0] + .data: [0x8065D690, 0x8065DBF8] + .bss: [0x8129F308, 0x8129F320] m_start_data_init.c: .text: [0x803EDEC0, 0x803EED30] .rodata: [0x806432E0, 0x806432F0] diff --git a/include/m_collision_bg.h b/include/m_collision_bg.h index 51ad160f..d7f9d2b3 100644 --- a/include/m_collision_bg.h +++ b/include/m_collision_bg.h @@ -181,6 +181,7 @@ extern void mCoBG_InitBoatCollision(); extern int mCoBG_CheckAttribute_BallRolling(s16* angles, const xyz_t* wpos); extern f32 mCoBG_CheckBallRollingArea(s16 angle, const xyz_t* wpos); extern int mCoBG_ExistHeightGap_KeepAndNow_Detail(xyz_t wpos); +extern int mCoBG_GetHoleNumber(xyz_t wpos); extern void mCoBG_InitMoveBgData(); extern void mCoBG_InitBlockBgCheckMode(); diff --git a/include/m_common_data.h b/include/m_common_data.h index 5ec23c46..993f6299 100644 --- a/include/m_common_data.h +++ b/include/m_common_data.h @@ -280,7 +280,7 @@ typedef struct common_data_s { /* 0x028894 */ s16 balloon_state; /* balloon's current state */ /* 0x028896 */ s16 balloon_last_spawn_min; /* last minute the balloon was spawned */ /* 0x028898 */ f32 balloon_spawn_percent; /* chance that a balloon will spawn */ - /* 0x02889C */ int nook_shop_state; /* adjusted based on any current events happening to Nook's shop */ + /* 0x02889C */ int tanuki_shop_status; /* adjusted based on any current events happening to Nook's shop */ /* 0x0288A0 */ u8 pad_connected; /* is gamepad 0 connected? */ /* 0x0288A1 */ u8 _288a1[0x02DB40 - 0x0288A1]; /* 0x02DB40 */ u8 auto_nwrite_set; /* when true, saved nwrite time will be utilized. Seems to be used to keep same date for fishing tourney stuff. */ diff --git a/include/m_event.h b/include/m_event.h index 87bab987..e7c69c49 100644 --- a/include/m_event.h +++ b/include/m_event.h @@ -20,6 +20,9 @@ extern "C" { #define mEv_SCHEDULE_MULTIDAY 0x40 /* event scheduled over more than a single day */ #define mEv_SCHEDULE_TODAY 0x80 /* event will be active on the day loaded */ +#define mEv_TO_DAY(month_day) ((lbRTC_day_t)(month_day)) +#define mEv_TO_MONTH(month_day) ((lbRTC_month_t)((month_day) >> 8)) + typedef union event_monthday_s { struct { s8 month; @@ -499,6 +502,8 @@ extern mEv_place_data_c* mEv_get_common_place(int type, s8 id); extern void mEv_set_status(int event, s16 status); extern void mEv_GetEventWeather(s16* weather, s16* intensity); extern int mEv_CheckRealArbeit(); +extern int mEv_CheckEvent(u32 event); +extern u16 mEv_get_bargain_day(); extern int mEv_weekday2day(lbRTC_month_t month, int week_type, lbRTC_weekday_t weekday); extern void mEv_ClearEventInfo(); diff --git a/include/m_item_debug.h b/include/m_item_debug.h new file mode 100644 index 00000000..1260145a --- /dev/null +++ b/include/m_item_debug.h @@ -0,0 +1,41 @@ +#ifndef M_ITEM_DEBUG_H +#define M_ITEM_DEBUG_H + +#include "types.h" +#include "libu64/gfxprint.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + mItemDebug_CATEGORY_NONE, + mItemDebug_CATEGORY_FTR, + mItemDebug_CATEGORY_PPR, + mItemDebug_CATEGORY_MNY, + mItemDebug_CATEGORY_TOL, + mItemDebug_CATEGORY_FSH, + mItemDebug_CATEGORY_CLT, + mItemDebug_CATEGORY_ELS, + mItemDebug_CATEGORY_CPT, + mItemDebug_CATEGORY_WLL, + mItemDebug_CATEGORY_FOD, + mItemDebug_CATEGORY_PLT, + mItemDebug_CATEGORY_MSC, + mItemDebug_CATEGORY_DST, + mItemDebug_CATEGORY_LOT, + mItemDebug_CATEGORY_IST, + mItemDebug_CATEGORY_HPY, + mItemDebug_CATEGORY_KAB, + + mItemDebug_CATEGORY_NUM +}; + +extern void mItemDebug_ItemDebugMain(); +extern void mItemDebug_ItemDebugDraw(gfxprint_t* gfxprint); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/m_name_table.h b/include/m_name_table.h index 4390d2fc..039d8f52 100644 --- a/include/m_name_table.h +++ b/include/m_name_table.h @@ -168,6 +168,13 @@ extern mActor_name_t bg_item_fg_sub_dig2take_conv(mActor_name_t item); #define HUKUBUKURO_NUM 2 #define KABU_NUM 4 +#define PAPER_UNIQUE_NUM 64 +#define PAINT_NUM 12 +#define FLOWER_NUM 9 +#define HANIWA_NUM 127 +#define NOT_SECRET_MD_NUM 52 +#define UMBRELLA_NUM 32 + #define EMPTY_NO 0x0000 #define TREE_STUMP001 (EMPTY_NO + 1) #define TREE_STUMP002 (EMPTY_NO + 2) @@ -449,7 +456,7 @@ extern mActor_name_t bg_item_fg_sub_dig2take_conv(mActor_name_t item); #define SIGNBOARD7_PLR3 (SIGNBOARD6_PLR3 + 1) #define FTR0_START 0x1000 - +#define FTR_CLASSIC_WARDROBE 0x1004 #define FTR_PAPA_BEAR 0x10E8 #define FTR_PAPA_BEAR_EAST 0x10E9 #define FTR_PAPA_BEAR_NORTH 0x10EA @@ -504,10 +511,37 @@ extern mActor_name_t bg_item_fg_sub_dig2take_conv(mActor_name_t item); #define FTR_UMBRELLA31_WEST 0x1D87 +#define FTR_FAMICOM_CLU_CLU_LAND 0x1DA8 +#define FTR_FAMICOM_BALLOON_FIGHT 0x1DAC +#define FTR_FAMICOM_DONKEY_KONG 0x1DB0 +#define FTR_FAMICOM_DK_JR_MATCH 0x1DB4 +#define FTR_FAMICOM_PINBALL 0x1DB8 +#define FTR_FAMICOM_TENNIS 0x1DBC +#define FTR_FAMICOM_GOLF 0x1DC0 +#define FTR_FAMICOM_PUNCHOUT 0x1DC4 +#define FTR_FAMICOM_BASEBALL 0x1DC8 +#define FTR_FAMICOM_CLU_CLU_LAND_DISK 0x1DCC +#define FTR_FAMICOM_DONKEY_KONG_3 0x1DD0 +#define FTR_FAMICOM_DONKEY_KONG_JR 0x1DD4 +#define FTR_FAMICOM_SOCCER 0x1DD8 +#define FTR_FAMICOM_EXCITEBIKE 0x1DDC +#define FTR_FAMICOM_WARIOS_WOODS 0x1DE0 +#define FTR_FAMICOM_ICE_CLIMBERS 0x1DE4 +#define FTR_FAMICOM_MARIO_BROS 0x1DE8 +#define FTR_FAMICOM_SUPER_MARIO_BROS 0x1DEC +#define FTR_FAMICOM_LEGEND_OF_ZELDA 0x1DF0 +#define FTR_FAMICOM 0x1DF4 + #define FTR_TAPEDECK 0x1E58 +#define FTR_BIG_FESTIVE_TREE 0x1E88 + +#define FTR_FESTIVE_TREE 0x1EBC + #define FTR_DINO_TRICERA_SKULL 0x1EEC +#define FTR_DINO_TREX_SKULL 0x1EF8 + #define FTR_DINO_TRILOBITE_WEST 0x1F4F #define FTR_DINO_DISP_TRICERA 0x1F7C @@ -595,7 +629,7 @@ extern mActor_name_t bg_item_fg_sub_dig2take_conv(mActor_name_t item); #define ITM_PAPER_STACK_TWO_START 0x2040 #define ITM_PAPER_STACK_THREE_START 0x2080 #define ITM_PAPER_STACK_FOUR_START 0x20C0 -#define ITM_PAPER_END 0x20FF +#define ITM_PAPER_END (ITM_PAPER_START + 256) #define ITM_MONEY_START 0x2100 #define ITM_MONEY_1000 ITM_MONEY_START // 0x2100 @@ -993,15 +1027,17 @@ extern mActor_name_t bg_item_fg_sub_dig2take_conv(mActor_name_t item); #define ITM_FOSSIL (ITM_DUST2_OLD_TIRE + 1) #define ITM_PITFALL (ITM_FOSSIL + 1) #define ITM_FORTUNE_SLIP (ITM_PITFALL + 1) -#define ITM_SHELL0 (ITM_FORTUNE_SLIP + 1) -#define ITM_SHELL1 (ITM_SHELL0 + 1) -#define ITM_SHELL2 (ITM_SHELL1 + 1) -#define ITM_SHELL3 (ITM_SHELL2 + 1) -#define ITM_SHELL4 (ITM_SHELL3 + 1) -#define ITM_SHELL5 (ITM_SHELL4 + 1) -#define ITM_SHELL6 (ITM_SHELL5 + 1) -#define ITM_SHELL7 (ITM_SHELL6 + 1) -#define ITM_PRESENT (ITM_SHELL7 + 1) +#define ITM_SHELL_START (ITM_ETC_START + 20) +#define ITM_SHELL0 (ITM_SHELL_START + 0) +#define ITM_SHELL1 (ITM_SHELL_START + 1) +#define ITM_SHELL2 (ITM_SHELL_START + 2) +#define ITM_SHELL3 (ITM_SHELL_START + 3) +#define ITM_SHELL4 (ITM_SHELL_START + 4) +#define ITM_SHELL5 (ITM_SHELL_START + 5) +#define ITM_SHELL6 (ITM_SHELL_START + 6) +#define ITM_SHELL7 (ITM_SHELL_START + 7) +#define ITM_SHELL_END (ITM_SHELL_START + 8) +#define ITM_PRESENT (ITM_ETC_START + 28) #define ITM_TOWN_MAP (ITM_PRESENT + 1) #define ITM_SIGNBOARD (ITM_TOWN_MAP + 1) #define ITM_GOLDEN_NET_PRESENT (ITM_SIGNBOARD + 1) @@ -1025,8 +1061,12 @@ extern mActor_name_t bg_item_fg_sub_dig2take_conv(mActor_name_t item); #define ITM_ETC_END 0x2531 #define ITM_CARPET_START 0x2600 +#define ITM_CARPET00 (ITM_CARPET_START + 0) +#define ITM_CARPET_END (ITM_CARPET_START + 71) #define ITM_WALL_START 0x2700 +#define ITM_WALL00 (ITM_WALL_START + 0) +#define ITM_WALL_END (ITM_WALL_START + 71) #define ITM_FOOD_START 0x2800 #define ITM_FOOD_APPLE (ITM_FOOD_START + 0) @@ -1055,9 +1095,23 @@ extern mActor_name_t bg_item_fg_sub_dig2take_conv(mActor_name_t item); #define ITM_MINIDISK_START 0x2A00 #define ITM_DIARY_START 0x2B00 -#define ITM_COLLEGERULE ITM_DIARY_START -#define ITM_CALLIGRAPHY_PAD 0x2B0F -#define ITM_DIARY_END 0x2B10 +#define ITM_DIARY00 (ITM_DIARY_START + 0) +#define ITM_DIARY01 (ITM_DIARY_START + 1) +#define ITM_DIARY02 (ITM_DIARY_START + 2) +#define ITM_DIARY03 (ITM_DIARY_START + 3) +#define ITM_DIARY04 (ITM_DIARY_START + 4) +#define ITM_DIARY05 (ITM_DIARY_START + 5) +#define ITM_DIARY06 (ITM_DIARY_START + 6) +#define ITM_DIARY07 (ITM_DIARY_START + 7) +#define ITM_DIARY08 (ITM_DIARY_START + 8) +#define ITM_DIARY09 (ITM_DIARY_START + 9) +#define ITM_DIARY10 (ITM_DIARY_START + 10) +#define ITM_DIARY11 (ITM_DIARY_START + 11) +#define ITM_DIARY12 (ITM_DIARY_START + 12) +#define ITM_DIARY13 (ITM_DIARY_START + 13) +#define ITM_DIARY14 (ITM_DIARY_START + 14) +#define ITM_DIARY15 (ITM_DIARY_START + 15) +#define ITM_DIARY_END (ITM_DIARY_START + 16) #define ITM_TICKET_START 0x2C00 @@ -1109,10 +1163,17 @@ extern mActor_name_t bg_item_fg_sub_dig2take_conv(mActor_name_t item); #define ITM_SPIRIT4 (ITM_INSECT_START + 44) #define ITM_INSECT_END (ITM_INSECT_START + 45) -#define ITM_KABU_10 0x2F00 -#define ITM_KABU_50 0x2F01 -#define ITM_KABU_100 0x2F02 -#define ITM_KABU_SPOILED 0x2F03 +#define ITM_HUKUBUKURO_START 0x2E00 +#define ITM_HUKUBUKURO_BAG (ITM_HUKUBUKURO_START + 0) +#define ITM_HUKUBUKURO_PRESENT (ITM_HUKUBUKURO_START + 1) +#define ITM_HUKUBUKURO_END (ITM_HUKUBUKURO_START + 2) + +#define ITM_KABU_START 0x2F00 +#define ITM_KABU_10 (ITM_KABU_START + 0) +#define ITM_KABU_50 (ITM_KABU_START + 1) +#define ITM_KABU_100 (ITM_KABU_START + 2) +#define ITM_KABU_SPOILED (ITM_KABU_START + 3) +#define ITM_KABU_END (ITM_KABU_START + 4) #define FTR1_START 0x3000 @@ -1122,13 +1183,19 @@ extern mActor_name_t bg_item_fg_sub_dig2take_conv(mActor_name_t item); #define FTR_POLICE_MODEL 0x302C #define FTR_MUSEUM_MODEL 0x3030 +#define FTR_LOCOMOTIVE_MODEL 0x30A0 + +#define FTR_TRAIN_CAR_MODEL 0x30F4 #define FTR_ORANGEBOX 0x30F8 #define FTR_COLLEGERULE 0x30FC #define FTR_CALLIGRAPHY_PAD_WEST 0x313B +#define FTR_FESTIVE_FLAG 0x327C + #define FTR_MAILBOX 0x3294 +#define FTR_FESTIVE_CANDLE 0x3298 #define FTR1_END 0x3000 @@ -1257,6 +1324,7 @@ extern mActor_name_t bg_item_fg_sub_dig2take_conv(mActor_name_t item); #define SNOWMAN7 (SNOWMAN6 + 1) #define SNOWMAN8 (SNOWMAN7 + 1) #define TRAIN_DOOR 0xA011 +#define ACTOR_PROP_VILLAGER_SIGNBOARD 0xA012 #define SP_NPC_START 0xD000 #define SP_NPC_ARTIST (SP_NPC_START + 0) // D000 diff --git a/include/m_room_type.h b/include/m_room_type.h index ed92e80a..0af92640 100644 --- a/include/m_room_type.h +++ b/include/m_room_type.h @@ -146,5 +146,6 @@ extern int mRmTp_Index2LightSwitchStatus(int index); extern int mRmTp_NowSceneLightSwitchON(); extern int mRmTp_NowSceneLightSwitchOFF(); extern void mRmTp_MakeFtrNoTable(mActor_name_t* dst, mActor_name_t* src); +extern u8* mRmTp_CheckFtrBirthInfoTop(); #endif \ No newline at end of file diff --git a/include/m_shop.h b/include/m_shop.h index baefb514..4e14a115 100644 --- a/include/m_shop.h +++ b/include/m_shop.h @@ -7,6 +7,7 @@ #include "m_personal_id.h" #include "m_actor_type.h" #include "game.h" +#include "m_item_debug.h" #ifdef __cplusplus extern "C" { @@ -16,6 +17,17 @@ extern "C" { #define mSP_GOODS_COUNT 39 #define mSP_LOTTERY_ITEM_COUNT 3 +#define mSP_SIGNBOARD_PRICE 500 +#define mSP_FORIEGN_FRUIT_PRICE 2000 + +#define mSP_NET_SALES_SUM 3000 // minimum sales sum before net appears (Nook's Cranny only) +#define mSP_ROD_SALES_SUM 8000 // minimum sales sum before rod appears (Nook's Cranny only) +#define mSP_AXE_SALES_SUM 12000 // minimum sales sum before axe appears (Nook's Cranny only) + +#define mSP_COMBINI_SUM 25000 // sales sum for upgrading to Nook 'n' Go +#define mSP_SUPER_SUM 90000 // sales sum for upgrading to Nookway +#define mSP_DSUPER_SUM 240000 // sales sum for upgrading to Nookington's + /* item list groups */ enum { mSP_LIST_A, /* A priority list */ @@ -41,13 +53,6 @@ enum { mSP_LIST_HARVEST, mSP_LIST_MARIO, mSP_LIST_TENT, - mSP_LIST_DUMMY23, - mSP_LIST_DUMMY24, - mSP_LIST_DUMMY25, - mSP_LIST_DUMMY26, - mSP_LIST_DUMMY27, - mSP_LIST_DUMMY28, - mSP_LIST_DUMMY29, mSP_LIST_NUM }; @@ -89,8 +94,10 @@ enum { mSP_KIND_CLOTH, mSP_KIND_CARPET, mSP_KIND_WALLPAPER, + mSP_KIND_DIARY, - mSP_KIND_MAX + mSP_KIND_MAX = mSP_KIND_DIARY, + mSP_KIND_EXTENDED_MAX /* includes diary */ }; enum { @@ -101,6 +108,63 @@ enum { mSP_PRIORITY_NUM }; +enum { + mSP_CLOTH_SEASON_ANY, + mSP_CLOTH_SEASON_SPRING, + mSP_CLOTH_SEASON_SUMMER, + mSP_CLOTH_SEASON_AUTUMN, + mSP_CLOTH_SEASON_WINTER, + + mSP_CLOTH_SEASON_NUM +}; + +enum { + mSP_GOODS_TYPE_PAPER, + mSP_GOODS_TYPE_CLOTH, + mSP_GOODS_TYPE_FTR, + mSP_GOODS_TYPE_RARE_FTR, + mSP_GOODS_TYPE_CARPET, + mSP_GOODS_TYPE_WALL, + mSP_GOODS_TYPE_6, + mSP_GOODS_TYPE_7, + mSP_GOODS_TYPE_SAPLING, + mSP_GOODS_TYPE_TOOL, + mSP_GOODS_TYPE_PLANT, + + mSP_GOODS_TYPE_NUM +}; + +enum { + mSP_SHOP_TYPE_ZAKKA, + mSP_SHOP_TYPE_COMBINI, + mSP_SHOP_TYPE_SUPER, + mSP_SHOP_TYPE_DSUPER, + + mSP_SHOP_TYPE_NUM +}; + +enum { + mSP_SHOP_STATUS_PRE, + mSP_SHOP_STATUS_END, + mSP_SHOP_STATUS_OPEN, + mSP_SHOP_STATUS_RENEW, + mSP_SHOP_STATUS_PREEVENT, + mSP_SHOP_STATUS_ENDEVENT, + mSP_SHOP_STATUS_OPENEVENT, + + mSP_SHOP_STATUS_NUM +}; + +enum { + mSP_TANUKI_SHOP_STATUS_NORMAL, + mSP_TANUKI_SHOP_STATUS_EVENT, + mSP_TANUKI_SHOP_STATUS_HALLOWEEN, + mSP_TANUKI_SHOP_STATUS_FUKUBIKI, + mSP_TANUKI_SHOP_STATUS_HUKUBUKURO_SALE, + + mSP_TANUKI_SHOP_STATUS_NUM +}; + /* sizeof(mSP_goods_priority_list_c) == 1 */ typedef struct shop_goods_priority_list_s { u8 a:2; /* list A rarity */ @@ -131,20 +195,59 @@ typedef struct shop_s { /* 0x13C */ int visitor_flag; /* set when a foreign player enters Nook's shop, required for Nookington's */ } Shop_c; -extern void mSP_PrintNowShopSalesSum(gfxprint_t* gfxprint); -extern void mSP_SelectRandomItem_New(GAME* unused, mActor_name_t* item_tbl, int item_tbl_count, mActor_name_t* goods_exist_tbl, int goods_exist_tbl_count, int category, int list_type, int get_uncollected_item); -extern void mSP_RandomUmbSelect(mActor_name_t* item_buf, int item_buf_count); -extern int mSP_GetShopLevel(); -extern u32 mSP_ItemNo2ItemPrice(mActor_name_t item_no); -extern int mSP_SearchItemCategoryPriority(mActor_name_t item_no, int category, int priority, GAME* unused); // not sure if it's actually a GAME* -extern mActor_name_t mSP_RandomOneFossilSelect(int multi_fossil); -extern mActor_name_t mSP_RandomHaniwaSelect(mActor_name_t* item_buf, int num); -extern mActor_name_t mSP_SelectFishginPresent(int player_no); -extern mActor_name_t mSP_GetNowShopFgNum(); -extern mActor_name_t mSP_GetNowShopBgNum(); +extern mActor_name_t mSP_gc_famicom_table[]; -extern void mItemDebug_ItemDebugMain(); -extern void mItemDebug_ItemDebugDraw(gfxprint_t* gfxprint); +extern int mSP_CollectCheck(mActor_name_t item); +extern void mSP_SelectRandomItem_New(GAME* game, mActor_name_t* goods_table, int goods_count, mActor_name_t* goods_exist_table, int goods_exist_count, int category, int list_type, int uncollected_only); +extern int mSP_ShopSaleReport(mActor_name_t sold_item, mActor_name_t* goods_table, int goods_count, mActor_name_t rsv_item); +extern u32 mSP_ItemNo2ItemPrice(mActor_name_t item_no); +extern int mSP_SearchItemCategoryPriority(mActor_name_t item_no, int category, int list_type, GAME* game); +extern int mSP_CountElementInGoodsList(); +extern int mSP_CheckExchangeDay2(); +extern int mSP_CheckExchangeMonth(); +extern void mSP_NewExchangeDay(); +extern void mSP_ShopItsumoChirashi(int house_no, int shop_level, mActor_name_t item, int type, int send_proc); +extern void mSP_SetShopRareFurnitureChirashi(int player_no, mActor_name_t* goods_list, int goods_count, GAME* game); +extern void mSP_SetRenewalChiraswhi_AppoDay(); +extern void mSP_ExchangeLineUp_InGame(GAME* game); +extern void mSP_PlusSales(u32 sum); +extern int mSP_SetNewVisitor(); +extern u32 mSP_GetSalesSum(); +extern int mSP_GetShopLevel(); +extern int mSP_RenewShopLevel(); +extern int mSP_GetRealShopLevel(); +extern int mSP_GetGoodsPercent(int priority); +extern void mSP_PrintNowShopSalesSum(gfxprint_t* gfxprint); +extern void mSP_GetGoodsPriority(u8* abc_priorities, int category); +extern void mSP_ExchangeLineUp_ZeldaMalloc(); +extern void mSP_LotteryLineUp_ZeldaMalloc(); +extern void mSP_ExchangeLineUp_GameAlloc(GAME* game); +extern void mSP_LotteryLineUp_GameAlloc(GAME* game); +extern void mSP_InitShopSaveData(); +extern void mSP_ShopGameStartCt(GAME* game); +extern mActor_name_t mSP_GetNowShopBgNum(); +extern int mSP_WhatSpecialSale(); +extern mActor_name_t mSP_GetNowShopFgNum(); +extern lbRTC_hour_t mSP_GetShopOpenTime(); +extern lbRTC_hour_t mSP_GetShopCloseTime(); +extern lbRTC_hour_t mSP_GetShopCloseTime_Bgm(); +extern int mSP_InRenewal(); +extern int mSP_ShopOpen(); +extern void mSP_RandomHaniwaSelect(mActor_name_t* haniwa_list, int count); +extern void mSP_RandomMDSelect(mActor_name_t* md_list, int count); +extern void mSP_RandomUmbSelect(mActor_name_t* umb_list, int count); +extern mActor_name_t mSP_RandomOneFossilSelect(int multi_fossil); +extern int mSP_Chk_HukubukuroSail(); +extern int mSP_CheckFukubikiDay(); +extern int mSP_SetGoods2ReservedPoint(mActor_name_t goods, mActor_name_t reserved_no); +extern int mSP_CheckHallowinDay(); +extern void mSP_SetTanukiShopStatus(); +extern int mSP_money_check(u32 amount); +extern void mSP_get_sell_price(u32 amount); +extern mActor_name_t mSP_SelectFishginPresent(int player_no); +extern void mSP_SelectRandomItemToAGB(); +extern const char* mSP_ShopStatus2String(int status); +extern mActor_name_t mSP_GetRandomStationToyItemNo(); #ifdef __cplusplus } diff --git a/rel/m_fuusen.c b/rel/m_fuusen.c index 396b001f..f99c306d 100644 --- a/rel/m_fuusen.c +++ b/rel/m_fuusen.c @@ -9,7 +9,7 @@ int fuusen_DEBUG_mode_flag; -extern void Balloon_init(GAME_PLAY*) { +extern void Balloon_init(GAME_PLAY* play) { Common_Set(balloon_state, Balloon_STATE_DEAD); Common_Set(balloon_last_spawn_min, 0); Common_Set(balloon_spawn_percent, 0.05f); diff --git a/rel/m_home.c b/rel/m_home.c index 5539a220..dada65d0 100644 --- a/rel/m_home.c +++ b/rel/m_home.c @@ -252,7 +252,7 @@ extern void mHm_SetDefaultPlayerRoomData(int home_no) { Save_Set(homes[home_no & 3].floors[mHm_ROOM_MAIN].layer_main.items[ut_z][ut_x], l_mHm_player_room_default_data[home_no & 3].item); Save_Set(homes[home_no & 3].floors[mHm_ROOM_MAIN].layer_main.items[1][1], FTR_ORANGEBOX); - Save_Set(homes[home_no & 3].floors[mHm_ROOM_MAIN].layer_secondary.items[1][1], ITM_COLLEGERULE); + Save_Set(homes[home_no & 3].floors[mHm_ROOM_MAIN].layer_secondary.items[1][1], ITM_DIARY00); for (i = 0; i < mHm_ROOM_NUM; i++) { Save_Set(homes[home_no & 3].floors[i].wall_floor.flooring_idx, l_mHm_player_room_default_data[home_no & 3].floor_num); diff --git a/rel/m_item_debug.c b/rel/m_item_debug.c new file mode 100644 index 00000000..b693c720 --- /dev/null +++ b/rel/m_item_debug.c @@ -0,0 +1,206 @@ +#include "m_item_debug.h" + +#include "libultra/libultra.h" +#include "game.h" +#include "m_room_type.h" +#include "padmgr.h" +#include "m_name_table.h" +#include "m_private.h" +#include "m_common_data.h" + +typedef struct item_debug_s { + int enabled; + int category; + int index; +} ItemDebug_c; + +static char* mItemDebug_category_name_table[mItemDebug_CATEGORY_NUM] = { + "\xC5\xBC", // untranslated JP + "FTR", + "PPR", + "MNY", + "TOL", + "FSH", + "CLT", + "ELS", + "CPT", + "WLL", + "FOD", + "PLT", + "MSC", + "DST", + "LOT", + "IST", + "HPY", + "KAB" +}; + +static mActor_name_t mItemDebug_category_start_no_table[mItemDebug_CATEGORY_NUM] = { + EMPTY_NO, + FTR0_NO_START, + ITM_PAPER_START, + ITM_MONEY_START, + ITM_TOOL_START, + ITM_FISH_START, + ITM_CLOTH_START, + ITM_ETC_START, + ITM_CARPET_START, + ITM_WALL_START, + ITM_FOOD_START, + ITM_ENV_START, + ITM_MINIDISK_START, + ITM_DIARY_START, + ITM_TICKET_START, + ITM_INSECT_START, + ITM_HUKUBUKURO_START, + ITM_KABU_START +}; + +static int mItemDebug_category_max_table[mItemDebug_CATEGORY_NUM] = { + 0, + FTR_NUM, + PAPER_NUM, + MONEY_NUM, + TOOL_NUM, + FISH_NUM, + CLOTH_NUM, + ETC_NUM, + CARPET_NUM, + WALL_NUM, + FRUIT_NUM, + PLANT_NUM, + MINIDISK_NUM, + DIARY_NUM, + TICKET_NUM, + INSECT_NUM, + HUKUBUKURO_NUM, + KABU_NUM +}; + +/* @unused ? mItemDebug_ItemDebugCt(...) */ + +static int mItemDebug_FurnitureCanUse(int ftr_idx) { + if (ftr_idx >= 0 && ftr_idx < FTR_NUM) { + u8* birth_info_p = mRmTp_CheckFtrBirthInfoTop(); + + if (birth_info_p[ftr_idx] == mRmTp_BIRTH_TYPE_UNOBTAINABLE || birth_info_p[ftr_idx] == mRmTp_BIRTH_TYPE_MY_ORIGINAL) { + return FALSE; + } + + return TRUE; + } + + return FALSE; +} + +static ItemDebug_c l_mItemDebug_work_data; + +extern void mItemDebug_ItemDebugMain() { + if ((gamePT->pads[PAD2].on.button & BUTTON_START) == BUTTON_START) { + l_mItemDebug_work_data.enabled = (l_mItemDebug_work_data.enabled + 1) & 1; + + if (l_mItemDebug_work_data.enabled != FALSE) { + bzero(&l_mItemDebug_work_data, sizeof(ItemDebug_c)); + l_mItemDebug_work_data.enabled = TRUE; + } + else { + bzero(&l_mItemDebug_work_data, sizeof(ItemDebug_c)); + } + } + + if (l_mItemDebug_work_data.enabled != FALSE) { + int category; + + if ((gamePT->pads[PAD2].on.button & BUTTON_DUP) == BUTTON_DUP) { + l_mItemDebug_work_data.index = 0; + l_mItemDebug_work_data.category++; + + if (l_mItemDebug_work_data.category > mItemDebug_CATEGORY_KAB) { + l_mItemDebug_work_data.category = 0; + } + } + + category = l_mItemDebug_work_data.category; + if (category != mItemDebug_CATEGORY_NONE) { + if ((gamePT->pads[PAD2].on.button & BUTTON_DRIGHT) == BUTTON_DRIGHT) { + /* Holding B increments by 10, holding A increments by 100 */ + if ((gamePT->pads[PAD2].now.button & BUTTON_B) == BUTTON_B) { + l_mItemDebug_work_data.index += 10; + } + else if ((gamePT->pads[PAD2].now.button & BUTTON_A) == BUTTON_A) { + l_mItemDebug_work_data.index += 100; + } + else { + l_mItemDebug_work_data.index++; + } + + if (l_mItemDebug_work_data.index > mItemDebug_category_max_table[category] - 1) { + l_mItemDebug_work_data.index = 0; + } + } + else if ((gamePT->pads[PAD2].on.button & BUTTON_DLEFT) == BUTTON_DLEFT) { + /* Holding B increments by 10, holding A increments by 100 */ + if ((gamePT->pads[PAD2].now.button & BUTTON_B) == BUTTON_B) { + l_mItemDebug_work_data.index -= 10; + } + else if ((gamePT->pads[PAD2].now.button & BUTTON_A) == BUTTON_A) { + l_mItemDebug_work_data.index -= 100; + } + else { + l_mItemDebug_work_data.index--; + } + + if (l_mItemDebug_work_data.index < 0) { + l_mItemDebug_work_data.index = 0; + } + } + } + + if ((gamePT->pads[PAD2].on.button & BUTTON_DDOWN) == BUTTON_DDOWN && category != mItemDebug_CATEGORY_NONE) { + int slot_idx = mPr_GetPossessionItemIdxWithCond(Common_Get(now_private), EMPTY_NO, mPr_ITEM_COND_NORMAL); + mActor_name_t item; + + if (category != mItemDebug_CATEGORY_FTR) { + item = mItemDebug_category_start_no_table[category] + l_mItemDebug_work_data.index; + } + else { + if (mItemDebug_FurnitureCanUse(l_mItemDebug_work_data.index)) { + item = mRmTp_FtrIdx2FtrItemNo(l_mItemDebug_work_data.index, mRmTp_DIRECT_SOUTH); + } + else { + return; + } + } + + if (slot_idx != -1) { + mPr_SetPossessionItem(Common_Get(now_private), slot_idx, item, mPr_ITEM_COND_NORMAL); + } + } + } +} + +extern void mItemDebug_ItemDebugDraw(gfxprint_t* gfxprint) { + int category = l_mItemDebug_work_data.category; + + if (l_mItemDebug_work_data.enabled != FALSE) { + gfxprint_color(gfxprint, 225, 225, 255, 255); + gfxprint_locate8x8(gfxprint, 3, 20); + + if (category != mItemDebug_CATEGORY_NONE) { + if (category == mItemDebug_CATEGORY_FTR) { + if (mItemDebug_FurnitureCanUse(l_mItemDebug_work_data.index)) { + gfxprint_printf(gfxprint, "%s:%d", mItemDebug_category_name_table[category], l_mItemDebug_work_data.index); + } + else { + gfxprint_printf(gfxprint, "%s:---(%d)", mItemDebug_category_name_table[category], l_mItemDebug_work_data.index); + } + } + else { + gfxprint_printf(gfxprint, "%s:%d", mItemDebug_category_name_table[category], l_mItemDebug_work_data.index); + } + } + else { + gfxprint_printf(gfxprint, "\xC5\xBC"); + } + } +} diff --git a/rel/m_mail.c b/rel/m_mail.c index bd7ecac2..63b8c4e8 100644 --- a/rel/m_mail.c +++ b/rel/m_mail.c @@ -243,7 +243,7 @@ static void mMl_get_mail_to_player_com(Mail_c* mail, PersonalID_c* recipient_pid mail->header.sender.type = mMl_NAME_TYPE_MUSEUM; mail->present = present; - mail->content.paper_type = (paper - ITM_PAPER_START) % 64; + mail->content.paper_type = (paper - ITM_PAPER_START) % PAPER_UNIQUE_NUM; } static int mMl_send_mail_box_com(PersonalID_c* recipient_pid, int player_no, Mail_c* mail, mActor_name_t present, mActor_name_t paper, int mail_no, u8* sender_name, u32 proc_type, u8 mail_type) { diff --git a/rel/m_mail_password_check.c b/rel/m_mail_password_check.c index 47ef820c..0c3067d8 100644 --- a/rel/m_mail_password_check.c +++ b/rel/m_mail_password_check.c @@ -1087,7 +1087,7 @@ extern int mMpswd_check_present_user(mActor_name_t item) { } else if ( (item >= ITM_RED_BALLOON && item <= ITM_BUNNY_O_BALLOON) || - (item >= ITM_COLLEGERULE && item <= ITM_CALLIGRAPHY_PAD) || + (item >= ITM_DIARY00 && item <= ITM_DIARY15) || (item >= ITM_BLUEBELL_FAN && item <= ITM_LEAF_FAN) || (item >= ITM_YELLOW_PINWHEEL && item <= ITM_FANCY_PINWHEEL) || (item >= ITM_GOLDEN_NET && item <= ITM_GOLDEN_ROD) || diff --git a/rel/m_shop.c b/rel/m_shop.c new file mode 100644 index 00000000..536b5017 --- /dev/null +++ b/rel/m_shop.c @@ -0,0 +1,2761 @@ +#include "m_shop.h" + +#include "game.h" +#include "m_cockroach.h" +#include "m_collision_bg.h" +#include "m_common_data.h" +#include "m_event.h" +#include "m_handbill.h" +#include "m_house.h" +#include "m_item_name.h" +#include "m_name_table.h" +#include "m_room_type.h" + +extern mActor_name_t* mSP_ftr_list[]; +extern mActor_name_t* mSP_binsen_list[]; +extern mActor_name_t* mSP_cloth_list[]; +extern mActor_name_t* mSP_carpet_list[]; +extern mActor_name_t* mSP_wall_list[]; + +static mActor_name_t diary_listA[6] = { + ITM_DIARY01, ITM_DIARY04, ITM_DIARY07, ITM_DIARY10, ITM_DIARY13, EMPTY_NO +}; + +static mActor_name_t diary_listB[6] = { + ITM_DIARY02, ITM_DIARY05, ITM_DIARY08, ITM_DIARY11, ITM_DIARY14, EMPTY_NO +}; + +static mActor_name_t diary_listC[7] = { + ITM_DIARY03, ITM_DIARY06, ITM_DIARY09, ITM_DIARY12, ITM_DIARY15, ITM_DIARY00, EMPTY_NO +}; + +static mActor_name_t* mSP_diary_list[mSP_LIST_NUM] = { + diary_listA, + diary_listB, + diary_listC, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static mActor_name_t** mSP_goods_seg_inf[mSP_KIND_EXTENDED_MAX] = { + mSP_ftr_list, + mSP_binsen_list, + mSP_cloth_list, + mSP_carpet_list, + mSP_wall_list, + mSP_diary_list +}; + +static void mSP_InitItemTable(mActor_name_t* item_table, int count) { + int i; + + if (item_table == NULL) { + return; + } + + for (i = 0; i < count; i++) { + *item_table++ = EMPTY_NO; + } +} + +static mActor_name_t* mSP_SelectListFromPriority(mActor_name_t** lists, u8* priorities, int list_type) { + mActor_name_t* list = NULL; + + switch (list_type) { + case mSP_LISTTYPE_EVENT: + list = lists[mSP_LIST_EVENT]; + break; + case mSP_LISTTYPE_TRAIN: + list = lists[mSP_LIST_TRAIN]; + break; + case mSP_LISTTYPE_LOTTERY: + list = lists[mSP_LIST_LOTTERY]; + break; + case mSP_LISTTYPE_HALLOWEEN: + list = lists[mSP_LIST_HALLOWEEN]; + break; + case mSP_LISTTYPE_HALLOWEEN2: + list = lists[mSP_LIST_HALLOWEEN2]; + break; + case mSP_LISTTYPE_PRESENT: + list = lists[mSP_LIST_PRESENT]; + break; + case mSP_LISTTYPE_CHRISTMAS: + list = lists[mSP_LIST_CHRISTMAS]; + break; + case mSP_LISTTYPE_SNOW: + list = lists[mSP_LIST_SNOW]; + break; + case mSP_LISTTYPE_JONASON: + list = lists[mSP_LIST_JONASON]; + break; + case mSP_LISTTYPE_POSTOFFICE: + list = lists[mSP_LIST_POSTOFFICE]; + break; + case mSP_LISTTYPE_NINTENDO64: + list = lists[mSP_LIST_NINTENDO64]; + break; + case mSP_LISTTYPE_SPECIALPRESENT: + list = lists[mSP_LIST_SPECIALPRESENT]; + break; + case mSP_LISTTYPE_ISLAND: + list = lists[mSP_LIST_ISLAND]; + break; + case mSP_LISTTYPE_ISLANDFAMICOM: + list = lists[mSP_LIST_ISLANDFAMICOM]; + break; + case mSP_LISTTYPE_HOMEPAGE: + list = lists[mSP_LIST_HOMEPAGE]; + break; + case mSP_LISTTYPE_EVENTPRESENTCHUMON: + list = lists[mSP_LIST_EVENTPRESENTCHUMON]; + break; + case mSP_LISTTYPE_KAMAKURA: + list = lists[mSP_LIST_KAMAKURA]; + break; + case mSP_LISTTYPE_HARVEST: + list = lists[mSP_LIST_HARVEST]; + break; + case mSP_LISTTYPE_MARIO: + list = lists[mSP_LIST_MARIO]; + break; + case mSP_LISTTYPE_TENT: + list = lists[mSP_LIST_TENT]; + break; + + case mSP_LISTTYPE_ABC: + default: + { + int i; + + for (i = 0; i < 3; i++, priorities++) { + if (list_type == priorities[0]) { + switch (i) { + case mSP_LISTTYPE_COMMON: + list = lists[mSP_LIST_A]; + break; + case mSP_LISTTYPE_UNCOMMON: + list = lists[mSP_LIST_B]; + break; + case mSP_LISTTYPE_RARE: + list = lists[mSP_LIST_C]; + break; + } + } + } + break; + } + } + + if (list == NULL) { + list = lists[mSP_LIST_A]; + } + + return list; +} + +static void mSP_SetSeasonFTR_local_december(mActor_name_t* item_table, int count, mActor_name_t ftr0, mActor_name_t ftr1) { + if (count > 1) { + item_table[0] = ftr0; + item_table[1] = ftr1; + } + else if (fqrand() < 0.5f) { + item_table[0] = ftr0; + } + else { + item_table[0] = ftr1; + } +} + +static void mSP_SetSeasonFTR(mActor_name_t* item_table, int count) { + lbRTC_time_c rtc_time = Common_Get(time.rtc_time); + lbRTC_month_t month = rtc_time.month; + lbRTC_day_t day = rtc_time.day; + + if (count > 0 && month == lbRTC_DECEMBER) { + + if (day <= 24) { + mSP_SetSeasonFTR_local_december(item_table, count, FTR_FESTIVE_TREE, FTR_BIG_FESTIVE_TREE); + } + else if (day >= 26) { + mSP_SetSeasonFTR_local_december(item_table, count, FTR_FESTIVE_CANDLE, FTR_FESTIVE_FLAG); + } + } +} + +static mActor_name_t* mSP_GetItemList(mActor_name_t** lists, u8* priorities, int list_type) { + if (list_type == mSP_LISTTYPE_ABC) { + int abc_roll = RANDOM(100); + int goods_power = mPr_GetGoodsPower(); + int rare_chance; + int uncommon_chance; + + if (goods_power < 0) { + uncommon_chance = goods_power + 40; /* [10%, 39%] */ + rare_chance = 5; /* always 5% chance */ + /* common_chance = [85%, 66%] */ + } + else { + rare_chance = goods_power + 5; /* [5%, 55%] */ + uncommon_chance = rare_chance + 35; /* always 35% chance */ + /* common_chance = [60%, 10%]*/ + } + + if (abc_roll < rare_chance) { + return mSP_SelectListFromPriority(lists, priorities, mSP_LISTTYPE_RARE); + } + else if (abc_roll < uncommon_chance) { + return mSP_SelectListFromPriority(lists, priorities, mSP_LISTTYPE_UNCOMMON); + } + else { + return mSP_SelectListFromPriority(lists, priorities, mSP_LISTTYPE_COMMON); + } + } + else { + return mSP_SelectListFromPriority(lists, priorities, list_type); + } +} + +static int mSP_GoodsExistAlready(mActor_name_t* goods_table, int count, mActor_name_t item) { + int i; + + if (goods_table != NULL) { + for (i = 0; i < count; i++) { + if (goods_table[i] == item) { + return TRUE; + } + } + } + + return FALSE; +} + +extern int mSP_CollectCheck(mActor_name_t item) { + mActor_name_t ftr_item = mRmTp_Item1ItemNo2FtrItemNo_AtPlayerRoom(item, FALSE); + u32* bitfield; + int idx; + + bitfield = NULL; + + switch (ITEM_NAME_GET_TYPE(ftr_item)) { + case NAME_TYPE_FTR0: + case NAME_TYPE_FTR1: + { + bitfield = Common_Get(now_private)->furniture_collected_bitfield; + idx = mRmTp_FtrItemNo2FtrIdx(ftr_item); + break; + } + + case NAME_TYPE_ITEM1: + { + switch (ITEM_NAME_GET_CAT(ftr_item)) { + case ITEM1_CAT_PAPER: + { + bitfield = Common_Get(now_private)->paper_collected_bitfield; + idx = (ftr_item - ITM_PAPER_START) % PAPER_UNIQUE_NUM; + break; + } + + case ITEM1_CAT_WALL: + { + bitfield = Common_Get(now_private)->wall_collected_bitfield; + idx = ftr_item - ITM_WALL_START; + break; + } + + case ITEM1_CAT_CARPET: + { + bitfield = Common_Get(now_private)->carpet_collected_bitfield; + idx = ftr_item - ITM_CARPET_START; + break; + } + + case ITEM1_CAT_MINIDISK: + { + bitfield = Common_Get(now_private)->music_collected_bitfield; + idx = (mActor_name_t)(ftr_item - ITM_MINIDISK_START); + break; + } + } + + break; + } + } + + if (bitfield == NULL) { + return FALSE; + } + + return ((1 << (idx & 0x1F)) & bitfield[idx >> 5]) != 0; +} + +static int mSP_CountElementInCommonList(mActor_name_t* list) { + int count = 0; + + for (list; list[0] != EMPTY_NO; list++, count++) { } + + return count; +} + +static int mSP_CountElementInCommonList_collect(mActor_name_t* list, int* selected_idx, int uncollected_only) { + int count = 0; + int selected; + mActor_name_t* list_p; + + if (uncollected_only == FALSE) { + count = mSP_CountElementInCommonList(list); + selected_idx[0] = RANDOM(count); + + return count; + } + + /* Count all uncollected items in the list */ + for (list_p = list; list_p[0] != EMPTY_NO; list_p++) { + if (mSP_CollectCheck(list_p[0]) == FALSE) { + count++; + } + } + + if (count == 0) { + selected_idx[0] = 0; + return 0; + } + + selected = RANDOM(count); + selected_idx[0] = 0; + for (list_p = list; list_p[0] != EMPTY_NO && selected > 0; list_p++) { + if (mSP_CollectCheck(list_p[0]) == FALSE) { + selected--; + } + + selected_idx[0]++; + } + + return count; +} + +static int mSP_get_cloth_season() { + lbRTC_time_c rtc_time = Common_Get(time.rtc_time); + lbRTC_month_t month = rtc_time.month; + int res; + + switch (month) { + case lbRTC_JANUARY: + res = mSP_CLOTH_SEASON_WINTER; + break; + + case lbRTC_FEBRUARY: + { + if (rtc_time.day > 24) { + res = mSP_CLOTH_SEASON_SPRING; + } + else { + res = mSP_CLOTH_SEASON_WINTER; + } + + break; + } + + case lbRTC_MARCH: + case lbRTC_APRIL: + res = mSP_CLOTH_SEASON_SPRING; + break; + + case lbRTC_MAY: + { + if (rtc_time.day > 26) { + res = mSP_CLOTH_SEASON_SUMMER; + } + else { + res = mSP_CLOTH_SEASON_SPRING; + } + + break; + } + + case lbRTC_JUNE: + case lbRTC_JULY: + res = mSP_CLOTH_SEASON_SUMMER; + break; + + case lbRTC_AUGUST: + { + if (rtc_time.day > 26) { + res = mSP_CLOTH_SEASON_AUTUMN; + } + else { + res = mSP_CLOTH_SEASON_SUMMER; + } + + break; + } + + case lbRTC_SEPTEMBER: + case lbRTC_OCTOBER: + res = mSP_CLOTH_SEASON_AUTUMN; + break; + + case lbRTC_NOVEMBER: + { + if (rtc_time.day > 26) { + res = mSP_CLOTH_SEASON_WINTER; + } + else { + res = mSP_CLOTH_SEASON_AUTUMN; + } + + break; + } + + case lbRTC_DECEMBER: + res = mSP_CLOTH_SEASON_WINTER; + break; + } + + return res; +} + +extern u8 cloth_season_cnt[]; + +static int mSP_CountElementInClothList(int* selected) { + u8* count_p = cloth_season_cnt; + int cloth_season = mSP_get_cloth_season(); + int cloth_count = count_p[mSP_CLOTH_SEASON_ANY] + count_p[cloth_season]; + + selected[0] = RANDOM(cloth_count); // random cloth selected + + if (selected[0] >= cloth_season_cnt[mSP_CLOTH_SEASON_ANY]) { + int i; + + /* seasonal cloths are sequential in the item lists, so add previous season counts to the selected index */ + for (i = mSP_CLOTH_SEASON_SPRING; i < cloth_season; i++) { + selected[0] += count_p[i]; + } + } + + return cloth_count; +} + +static int mSP_CountElementInClothList_collect(mActor_name_t* list, int* selected, int uncollected_only) { + u8* count_p = cloth_season_cnt; + + if (uncollected_only == FALSE) { + return mSP_CountElementInClothList(selected); + } + else { + int cloth_season; + int count; + mActor_name_t* list_p; + mActor_name_t* list_p2; + int uncollected_num; + int n; + int s; + int i; + cloth_season = mSP_get_cloth_season(); + uncollected_num = 0; + count = 0; + + for (list_p = list; count < count_p[mSP_CLOTH_SEASON_ANY] && list_p != NULL; list_p++) { + if (mSP_CollectCheck(list_p[0]) == FALSE) { + uncollected_num++; + } + + count++; + } + + n = count_p[mSP_CLOTH_SEASON_ANY]; + for (i = mSP_CLOTH_SEASON_SPRING; i < cloth_season; i++) { + n += count_p[i]; // add intermediate season counts + } + + i = n; + s = n + count_p[cloth_season]; + list_p2 = list + (int)n; + for (list_p = list_p2; i < s && list_p != NULL; list_p++) { + if (mSP_CollectCheck(list_p[0]) == FALSE) { + uncollected_num++; + } + + i++; + } + + if (uncollected_num == 0) { + selected[0] = 0; + return 0; + } + else { + int selected_idx = RANDOM(uncollected_num); + + count = 0; + selected[0] = 0; + for (list; count < count_p[mSP_CLOTH_SEASON_ANY] && list != NULL && selected_idx > 0; list++) { + if (mSP_CollectCheck(list[0]) == FALSE) { + selected_idx--; + } + + selected[0]++; + count++; + } + + i = n; + for (list_p2; i < s && list_p2 != NULL && selected_idx > 0; list_p2++) { + if (mSP_CollectCheck(list_p2[0]) == FALSE) { + selected_idx--; + } + + selected[0]++; + i++; + } + } + + return uncollected_num; + } +} + +static int mSP_NoList(mActor_name_t* items_table, int count, mActor_name_t* list) { + if (list == NULL) { + int i; + + for (i = 0; i < count; i++) { + items_table[0] = EMPTY_NO; + items_table++; + } + + return TRUE; + } + + return FALSE; +} + +static void mSP_SetDummyItem(mActor_name_t* items_table, int count, int kind) { + mActor_name_t dummy_table[mSP_KIND_EXTENDED_MAX] = { + FTR_CLASSIC_WARDROBE, + ITM_PAPER00, + ITM_CLOTH000, + ITM_CARPET00, + ITM_WALL00, + ITM_DIARY00 + }; + + mActor_name_t dummy_item = dummy_table[kind]; + int i; + + for (i = 0; i < count; i++) { + items_table[i] = dummy_item; + } +} + +extern void mSP_SelectRandomItem_New( + GAME* game, + mActor_name_t* goods_table, + int goods_count, + mActor_name_t* goods_exist_table, + int goods_exist_count, + int category, + int list_type, + int uncollected_only +) { + mSP_InitItemTable(goods_table, goods_count); + + if (goods_count != 0 && goods_table != NULL) { + if (goods_table != NULL) { + u8 abc_priorities[3]; + mActor_name_t** goods_seg_p = mSP_goods_seg_inf[category]; + int i = 0; + + mSP_GetGoodsPriority(abc_priorities, category); + + while (i < goods_count) { + mActor_name_t* item_list_p = mSP_GetItemList(goods_seg_p, abc_priorities, list_type); + int list_item_count; + int selected_idx; + + if (mSP_NoList(goods_table, goods_count, item_list_p) != FALSE) { + mSP_SetDummyItem(goods_table, goods_count, category); + return; + } + + if ( + category == mSP_KIND_CLOTH && + (list_type == mSP_LISTTYPE_ABC || list_type == mSP_LIST_A || list_type == mSP_LIST_B || list_type == mSP_LIST_C) + ) { + list_item_count = mSP_CountElementInClothList_collect(item_list_p, &selected_idx, uncollected_only); + } + else { + list_item_count = mSP_CountElementInCommonList_collect(item_list_p, &selected_idx, uncollected_only); + } + + if (list_item_count == 0) { + mSP_InitItemTable(goods_table, goods_count); + return; + } + + if ( + mSP_GoodsExistAlready(goods_table, goods_count, item_list_p[selected_idx]) == FALSE && + mSP_GoodsExistAlready(goods_exist_table, goods_exist_count, item_list_p[selected_idx]) == FALSE && + Save_Get(shop).rare_item != item_list_p[selected_idx] + ) { + goods_table[i] = item_list_p[selected_idx]; + i++; + } + else if (list_item_count < goods_count + goods_exist_count) { + /* forcibly add duplicate items if the list size is less than total possible goods */ + goods_table[i] = item_list_p[selected_idx]; + i++; + } + } + } + else { + mSP_SetDummyItem(goods_table, goods_count, category); // ????? + } + } +} + +static int mSP_CountPriceTableElement(u16* price_table) { + int n = 0; + + while (price_table[0] != 0xFFFF) { + price_table++; + n++; + } + + return n; +} + +extern int mSP_ShopSaleReport(mActor_name_t sold_item, mActor_name_t* goods_table, int goods_count, mActor_name_t rsv_item) { + int i; + + if (sold_item == ITM_HUKUBUKURO_BAG) { + Save_Get(shop).flowers_candy_grab_bag_count--; + return FALSE; + } + + if (sold_item == ITM_FOOD_CANDY) { + Save_Get(shop).flowers_candy_grab_bag_count--; + return FALSE; + } + + for (i = 0; i < goods_count; i++) { + if (sold_item == goods_table[i]) { + goods_table[i] = rsv_item; + return FALSE; + } + } + + if (sold_item == Save_Get(shop).rare_item) { + Save_Get(shop).rare_item = rsv_item; + return FALSE; + } + + return FALSE; +} + +extern u16 binsen_price_table[]; +extern u16 cloth_price_table[]; +extern u16 carpet_price_table[]; +extern u16 wall_price_table[]; +extern u16 tool_price_table[]; +extern u16 plant_price_table[]; +extern u16 food_price_table[]; +extern u16 fish_price_table[]; +extern u16 md_price_table[]; +extern u16 diary_price_table[]; +extern u16 insect_price_table[]; + +static u16* l_binsen_price_info = binsen_price_table; +static u16* l_cloth_price_info = cloth_price_table; +static u16* l_carpet_price_info = carpet_price_table; +static u16* l_wall_price_info = wall_price_table; +static u16* l_tool_price_info = tool_price_table; +static u16* l_plant_price_info = plant_price_table; +static u16* l_food_price_info = food_price_table; +static u16* l_fish_price_info = fish_price_table; +static u16* l_md_price_info = md_price_table; +static u16* l_diary_price_info = diary_price_table; +static u16* l_insect_price_info = insect_price_table; + +static u16** l_price_info[ITEM1_CAT_NUM] = { + &l_binsen_price_info, + NULL, + &l_tool_price_info, + &l_fish_price_info, + &l_cloth_price_info, + NULL, + &l_carpet_price_info, + &l_wall_price_info, + &l_food_price_info, + &l_plant_price_info, + &l_md_price_info, + &l_diary_price_info, + NULL, + &l_insect_price_info, + NULL, + NULL +}; + +static mActor_name_t mSP_item1_start_idx_table[ITEM1_CAT_NUM] = { + ITM_PAPER_START, + ITM_MONEY_START, + ITM_TOOL_START, + ITM_FISH_START, + ITM_CLOTH_START, + ITM_ETC_START, + ITM_CARPET_START, + ITM_WALL_START, + ITM_FOOD_START, + ITM_ENV_START, + ITM_MINIDISK_START, + ITM_DIARY_START, + ITM_TICKET_START, + ITM_INSECT_START, + ITM_HUKUBUKURO_START, + ITM_KABU_START +}; + +extern u16 ftr_price_table[]; + +extern u32 mSP_ItemNo2ItemPrice(mActor_name_t item_no) { + static u32 shellfish_price_table[ITM_SHELL_END - ITM_SHELL_START] = { + 160, 80, 600, 120, 240, 1800, 1400, 1000 + }; + + lbRTC_time_c rtc_time = Common_Get(time.rtc_time); + lbRTC_year_t year = rtc_time.year; + u32 price = 0; + + if (item_no == ITM_HUKUBUKURO_BAG) { + return year; + } + + item_no = mRmTp_FtrItemNo2Item1ItemNo(item_no, NULL); + if (item_no >= ITM_SHELL0 && item_no <= ITM_SHELL7) { + u32 idx = item_no - ITM_SHELL0; + + return shellfish_price_table[idx % 8]; + } + + if (item_no == ITM_SIGNBOARD) { + return mSP_SIGNBOARD_PRICE; + } + + switch (ITEM_NAME_GET_TYPE(item_no)) { + case NAME_TYPE_ITEM1: + { + u16** price_list_pp = l_price_info[ITEM_NAME_GET_CAT(item_no)]; + + if (price_list_pp != NULL && &price != NULL) { + u16* price_list_p = *price_list_pp; + int idx = item_no - mSP_item1_start_idx_table[ITEM_NAME_GET_CAT(item_no)]; + + if (item_no >= ITM_PAPER_START && item_no <= (ITM_PAPER_END - 1)) { + int paper_idx = (item_no - ITM_PAPER_START); + + idx = (item_no - ITM_PAPER_START) % PAPER_UNIQUE_NUM; + if (idx < mSP_CountPriceTableElement(price_list_p)) { + price = price_list_p[idx]; + price = price * ((paper_idx / 64) + 1); + return price; + } + } + + if (idx < mSP_CountPriceTableElement(price_list_p)) { + switch (item_no) { + case ITM_FOOD_APPLE: + case ITM_FOOD_CHERRY: + case ITM_FOOD_PEAR: + case ITM_FOOD_PEACH: + case ITM_FOOD_ORANGE: + { + if (Save_Get(fruit) != item_no) { + return mSP_FORIEGN_FRUIT_PRICE; + } + + break; + } + } + + + price = price_list_p[idx]; + return price; + } + + return 0; + } + + break; + } + + case NAME_TYPE_FTR0: + case NAME_TYPE_FTR1: + { + if (&price != NULL) { + int ftr_idx = mRmTp_FtrItemNo2FtrIdx(item_no); + u16* price_list_p = ftr_price_table; + + if (ftr_idx < mSP_CountPriceTableElement(price_list_p)) { + price = price_list_p[ftr_idx]; + return price; + } + + return 0; + } + + break; + } + + default: + { + return 0; + } + } + + return 0; +} + +extern int mSP_SearchItemCategoryPriority(mActor_name_t item_no, int category, int list_type, GAME* game) { + u8 abc_priorities[3]; + mActor_name_t** lists_p = mSP_goods_seg_inf[category]; + mActor_name_t* list_p; + int count; + int i; + + mSP_GetGoodsPriority(abc_priorities, category); + list_p = mSP_GetItemList(lists_p, abc_priorities, list_type); + count = mSP_CountElementInCommonList(list_p); + + if (list_p != NULL) { + for (i = 0; i < count; i++) { + if (item_no == list_p[i]) { + return TRUE; + } + } + } + + return FALSE; +} + +static int mSP_ItemNo2GoodsListCategory(mActor_name_t item_no) { + if (ITEM_IS_FTR(item_no)) { + return mSP_KIND_FURNITURE; + } + else if (item_no >= ITM_PAPER_START && item_no < ITM_PAPER_END) { + return mSP_KIND_PAPER; + } + else if (item_no >= ITM_CLOTH_START && item_no < ITM_CLOTH_END) { + return mSP_KIND_CLOTH; + } + else if (item_no >= ITM_WALL_START && item_no < ITM_WALL_END) { + return mSP_KIND_WALLPAPER; + } + else if (item_no >= ITM_CARPET_START && item_no < ITM_CARPET_END) { + return mSP_KIND_CARPET; + } + else if (item_no >= ITM_DIARY_START && item_no <= (ITM_DIARY_END-1)) { + return mSP_KIND_DIARY; + } + + return -1; +} + +static u8 l_zakka_goods[mSP_GOODS_TYPE_NUM] = { + 1, // stationery + 1, // clothing + 1, // ABC ftr + 0, // rare ftr + 1, // carpet + 1, // wallpaper + 1, // ?? + 0, // ?? + 1, // saplings + 2, // tools + 2 // plants +}; + +static u8 l_conbini_goods[mSP_GOODS_TYPE_NUM] = { + 2, // stationery + 2, // clothing + 2, // ABC ftr + 0, // rare ftr + 1, // carpet + 1, // wallpaper + 1, // ?? + 0, // ?? + 1, // saplings + 3, // tools + 3 // plants +}; + +static u8 l_super_goods[mSP_GOODS_TYPE_NUM] = { + 2, // stationery + 3, // clothing + 3, // ABC ftr + 1, // rare ftr + 2, // carpet + 2, // wallpaper + 1, // ?? + 0, // ?? + 2, // saplings + 2, // tools + 4 // plants +}; + +static u8 l_dsuper_goods[mSP_GOODS_TYPE_NUM] = { + 4, // stationery + 5, // clothing + 5, // ABC ftr + 1, // rare ftr + 3, // carpet + 3, // wallpaper + 1, // ?? + 0, // ?? + 3, // saplings + 3, // tools + 5 // plants +}; + +static u8* l_goods_count_table[mSP_SHOP_TYPE_NUM] = { + l_zakka_goods, + l_conbini_goods, + l_super_goods, + l_dsuper_goods +}; + +static void mSP_MakeRandomGoodsList(GAME* game, int* count, mActor_name_t* goods_list) { + int shop_level = mSP_GetShopLevel(); + u8* goods_count = l_goods_count_table[shop_level]; + Shop_c* shop = Save_GetPointer(shop); + mActor_name_t rare; + + /* roll rare furniture if the shop has one */ + if (goods_count[mSP_GOODS_TYPE_RARE_FTR] != 0) { + mSP_SelectRandomItem_New(game, &rare, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_RARE, FALSE); + } + else { + rare = EMPTY_NO; + } + + Save_Get(shop).rare_item = rare; + + /* roll ABC list furniture */ + mSP_SelectRandomItem_New(game, goods_list + count[0], goods_count[mSP_GOODS_TYPE_FTR], NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_ABC, FALSE); + mSP_SetSeasonFTR(goods_list + count[0], goods_count[mSP_GOODS_TYPE_FTR]); // replace with seasonal furniture if necessary + count[0] += goods_count[mSP_GOODS_TYPE_FTR]; + + /* check for grab bag sale */ + if (mSP_Chk_HukubukuroSail()) { + shop->flowers_candy_grab_bag_count += (s8)goods_count[mSP_GOODS_TYPE_PAPER]; + if (shop_level >= mSP_SHOP_TYPE_SUPER) { + shop->flowers_candy_grab_bag_count += 1; + } + } + else { + /* no grab bag sale, so roll paper & diaries */ + mSP_SelectRandomItem_New(game, goods_list + count[0], goods_count[mSP_GOODS_TYPE_PAPER], NULL, 0, mSP_KIND_PAPER, mSP_LISTTYPE_ABC, FALSE); + count[0] += goods_count[mSP_GOODS_TYPE_PAPER]; + + /* only roll diaries for Nookway or higher */ + if (shop_level >= mSP_SHOP_TYPE_SUPER) { + mSP_SelectRandomItem_New(game, goods_list + count[0], 1, NULL, 0, mSP_KIND_DIARY, mSP_LISTTYPE_ABC, FALSE); + count[0] += 1; + } + } + + /* roll clothing */ + mSP_SelectRandomItem_New(game, goods_list + count[0], goods_count[mSP_GOODS_TYPE_CLOTH], NULL, 0, mSP_KIND_CLOTH, mSP_LISTTYPE_ABC, FALSE); + count[0] += goods_count[mSP_GOODS_TYPE_CLOTH]; + + /* roll carpets */ + mSP_SelectRandomItem_New(game, goods_list + count[0], goods_count[mSP_GOODS_TYPE_CARPET], NULL, 0, mSP_KIND_CARPET, mSP_LISTTYPE_ABC, FALSE); + count[0] += goods_count[mSP_GOODS_TYPE_CARPET]; + + /* roll wallpaper */ + mSP_SelectRandomItem_New(game, goods_list + count[0], goods_count[mSP_GOODS_TYPE_WALL], NULL, 0, mSP_KIND_WALLPAPER, mSP_LISTTYPE_ABC, FALSE); + count[0] += goods_count[mSP_GOODS_TYPE_WALL]; +} + +extern int mSP_CountElementInGoodsList() { + mActor_name_t* items = Save_Get(shop).items; + int goods_count = 0; + int i; + + for (i = 0; i < mSP_GOODS_COUNT; i++) { + if (items[i] != EMPTY_NO) { + goods_count++; + } + } + + return goods_count; +} + +static void mSP_SelectTool(mActor_name_t* goods_list, int* count, int tool_num, int shop_level) { + static int table[4] = { ITM_SHOVEL, ITM_NET, ITM_ROD, ITM_AXE }; + + int tools_added = 0; + u16 paint_idx = Save_Get(shop).shop_info.paint_color; + u32 sales_sum = Save_Get(shop).sales_sum; + f32 tool_max; + + /* tool lockout based on sales sum is only applicable to Nook's Cranny */ + if (shop_level > mSP_SHOP_TYPE_ZAKKA) { + tool_max = 4;/* shove, net, rod, axe */ + } + else if (sales_sum < mSP_NET_SALES_SUM) { + tool_max = 1; /* shovel only */ + } + else if (sales_sum < mSP_ROD_SALES_SUM) { + tool_max = 2; /* shovel, net */ + } + else if (sales_sum < mSP_AXE_SALES_SUM) { + tool_max = 3; /* shovel, net, rod */ + } + else { + tool_max = 4; /* shove, net, rod, axe */ + } + + if (tool_num > (int)tool_max) { + tool_num = (int)tool_max; + } + + /* + This implementation kind of sucks. + At best case there's a (1/4)^4 (~0.4%) chance of + rolling all four unique tools in a single go. + */ + while (tools_added < tool_num) { + int idx = RANDOM_F(tool_max); + mActor_name_t tool = table[idx]; + + /* Don't allow duplicate tools */ + if (mSP_GoodsExistAlready(goods_list, count[0], tool) == FALSE) { + goods_list[(int)count[0]] = tool; + tools_added++; + count[0]++; + } + } + + /* Add paint & signboard if shop is Nookway or greater */ + if (shop_level >= mSP_SHOP_TYPE_SUPER) { + if (paint_idx >= PAINT_NUM) { + paint_idx = 0; /* wrap over to beginning */ + } + + goods_list[count[0]] = ITM_RED_PAINT + paint_idx; + paint_idx++; + Save_Get(shop).shop_info.paint_color = paint_idx; + count[0]++; + goods_list[count[0]] = ITM_SIGNBOARD; + count[0]++; + } + + /* Add umbrella */ + mSP_RandomUmbSelect(goods_list + count[0], 1); + count[0]++; +} + +static void mSP_SelectPlant(mActor_name_t* goods_list, int* count, int flower_count, int sapling_count, int shop_level) { + u8 flower_use[FLOWER_NUM]; + int i; + + if (mSP_CheckHallowinDay()) { + Save_Get(shop).flowers_candy_grab_bag_count = flower_count; + flower_count = sapling_count; + sapling_count = 0; + } + + if (shop_level >= mSP_SHOP_TYPE_SUPER && sapling_count > 0) { + goods_list[count[0]] = ITM_CEDAR_SAPLING; + sapling_count--; + count[0] += 1; + } + + for (i = 0; i < sapling_count; i++) { + goods_list[count[0]] = ITM_SAPLING; + count[0] += 1; + } + + for (i = 0; i < FLOWER_NUM; i++) { + flower_use[i] = FALSE; + } + + while (flower_count > 0) { + int idx = RANDOM(FLOWER_NUM); + + if (flower_use[idx] == FALSE) { + goods_list[count[0]] = ITM_WHITE_PANSY_BAG + idx; + flower_use[idx] = TRUE; + flower_count--; + count[0] += 1; + } + } +} + +static void mSP_MakeGoodsList(GAME* game) { + int count = 0; + mActor_name_t* shop_items = Save_Get(shop).items; + Shop_c* shop = Save_GetPointer(shop); + int shop_level = mSP_GetShopLevel(); + u8* goods_count = l_goods_count_table[shop_level]; + u8 tool_count = goods_count[mSP_GOODS_TYPE_TOOL]; + u8 flower_count = goods_count[mSP_GOODS_TYPE_PLANT]; + u8 sapling_count = goods_count[mSP_GOODS_TYPE_SAPLING]; + + if (mSP_CheckFukubikiDay() == FALSE) { + if (mSP_Chk_HukubukuroSail() != FALSE) { + shop->flowers_candy_grab_bag_count = 0; + } + + mSP_MakeRandomGoodsList(game, &count, shop_items); + + if (mSP_Chk_HukubukuroSail() != FALSE) { + shop->flowers_candy_grab_bag_count += (s8)tool_count; + shop->flowers_candy_grab_bag_count += (s8)flower_count; + shop->flowers_candy_grab_bag_count += (s8)sapling_count; + + if (shop_level >= mSP_SHOP_TYPE_SUPER) { + shop->flowers_candy_grab_bag_count++; // add signboard & paint + shop->flowers_candy_grab_bag_count++; + } + } + else { + mSP_SelectTool(shop_items, &count, tool_count, shop_level & 3); + mSP_SelectPlant(shop_items, &count, flower_count, sapling_count, shop_level & 3); + } + } +} + +static void mSP_MakeLotteryList(GAME* game) { + mActor_name_t* lottery_items = Save_Get(shop).lottery_items; + mActor_name_t unobtained_lottery_item; + + mSP_SelectRandomItem_New( + game, + &unobtained_lottery_item, + 1, + NULL, + 0, + mSP_KIND_FURNITURE, + mSP_LISTTYPE_LOTTERY, + TRUE + ); + + if (unobtained_lottery_item == EMPTY_NO) { + mSP_SelectRandomItem_New( + game, + lottery_items, + mSP_LOTTERY_ITEM_COUNT, + NULL, + 0, + mSP_KIND_FURNITURE, + mSP_LISTTYPE_LOTTERY, + FALSE + ); + } + else { + mSP_SelectRandomItem_New( + game, + lottery_items + 1, + mSP_LOTTERY_ITEM_COUNT - 1, + &unobtained_lottery_item, + 1, + mSP_KIND_FURNITURE, + mSP_LISTTYPE_LOTTERY, + FALSE + ); + + lottery_items[0] = unobtained_lottery_item; + } +} + +extern int mSP_CheckExchangeDay2() { + Shop_c* shop = Save_GetPointer(shop); + lbRTC_time_c rtc_time = Common_Get(time.rtc_time); + int res = lbRTC_IsEqualTime( + &rtc_time, + &shop->exchange_time, + lbRTC_CHECK_DAYS | lbRTC_CHECK_MONTHS | lbRTC_CHECK_YEARS + ); + + return res == lbRTC_EQUAL; +} + +extern int mSP_CheckExchangeMonth() { + Shop_c* shop = Save_GetPointer(shop); + lbRTC_time_c rtc_time = Common_Get(time.rtc_time); + int res = lbRTC_IsEqualTime( + &rtc_time, + &shop->exchange_time, + lbRTC_CHECK_MONTHS | lbRTC_CHECK_YEARS + ); + + return res == lbRTC_EQUAL; +} + +extern void mSP_NewExchangeDay() { + Save_Get(shop).exchange_time = Common_Get(time.rtc_time); +} + +/* @unused size: 0x104 */ +// ? mSP_SearchRareFurniture(...) + +extern void mSP_ShopItsumoChirashi(int house_no, int shop_level, mActor_name_t item, int type, int send_proc) { + static int rare_chirashi_bunmen[mSP_SHOP_TYPE_NUM][2] = { + { 18, 18 }, + { 19, 19 }, + { 21, 20 }, + { 23, 22 } + }; + + if (Save_Get(homes[house_no]).ownerID.land_id != 0xFFFF) { + int free_mail_idx = mMl_chk_mail_free_space(Save_Get(homes[house_no]).mailbox, HOME_MAILBOX_SIZE); + + if (mEv_ArbeitPlayer(mHS_get_pl_no(house_no) & 3) != TRUE) { + u8 item_name_str[mIN_ITEM_NAME_LEN]; + Mail_c leaflet; + int header_back_start; + + mIN_copy_name_str(item_name_str, item); + mHandbill_Set_free_str(mHandbill_FREE_STR7, item_name_str, mIN_ITEM_NAME_LEN); + mMl_clear_mail(&leaflet); + mHandbill_Load_HandbillFromRom( + leaflet.content.header, + &header_back_start, + leaflet.content.footer, + leaflet.content.body, + rare_chirashi_bunmen[shop_level][type & 1] + ); + leaflet.content.font = mMl_FONT_0; + leaflet.content.header_back_start = header_back_start; + leaflet.content.mail_type = mMl_TYPE_SHOP_SALE_LEAFLET; + leaflet.content.paper_type = ITM_PAPER55; // simple paper + + switch (send_proc) { + case mPO_SENDTYPE_MAIL: + { + mPO_receipt_proc(&leaflet, mPO_SENDTYPE_LEAFLET); + + break; + } + + default: + { + if (free_mail_idx >= 0) { + mPr_CopyPersonalID(&leaflet.header.recipient.personalID, &Save_Get(private[mHS_get_pl_no(house_no) & 3]).player_ID); + leaflet.header.recipient.type = mMl_NAME_TYPE_PLAYER; + + mMl_copy_mail(Save_Get(homes[house_no]).mailbox + free_mail_idx, &leaflet); + } + + break; + } + } + } + } +} + +extern void mSP_SetShopRareFurnitureChirashi(int player_no, mActor_name_t* goods_list, int goods_count, GAME* game) { + const int p = player_no; + int shop_level = mSP_GetShopLevel(); + int is_rare_item = FALSE; + mActor_name_t rare_item = EMPTY_NO; + int arrange_idx = mHS_get_arrange_idx(p); + lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time); + + if (player_no != mHS_get_pl_no_detail(arrange_idx)) { + mCkRh_SavePlayTime(player_no); + return; + } + + /* Check if we're on the last day of the month */ + if (Common_Get(time.rtc_time).day == lbRTC_GetDaysByMonth(Common_Get(time.rtc_time).year, + Common_Get(time.rtc_time).month)) { + mCkRh_SavePlayTime(player_no); + } else if (mEv_CheckEvent(mEv_SAVED_RENEWSHOP) == TRUE) { + mCkRh_SavePlayTime(player_no); // shop was already 'renewed' today + } else { + u16 bargain_day = mEv_get_bargain_day(); + lbRTC_time_c goki_time; + mHm_hs_c* home; + + if (bargain_day != 0) { + u32 month = mEv_TO_MONTH(bargain_day); + u32 day = mEv_TO_DAY(bargain_day); + if (Common_Get(time.rtc_time).month == month && + Common_Get(time.rtc_time).day == day) { + mCkRh_SavePlayTime(player_no); // shop 'bargin' event is active + return; + } + } + + goki_time = Save_Get(homes[arrange_idx]).goki.time; + lbRTC_Add_DD(&goki_time, 1); + home = Save_GetPointer(homes[arrange_idx]); + + /* check if the current date & time is past the renew time */ + if (home->goki.time.year == rtc_time->year && + home->goki.time.month == rtc_time->month && + home->goki.time.day == rtc_time->day) return; + + if (goki_time.year == rtc_time->year && + goki_time.month == rtc_time->month && + goki_time.day == rtc_time->day && + goki_time.hour < mTM_FIELD_RENEW_HOUR) return; + + if (rtc_time->hour < mTM_FIELD_RENEW_HOUR || + rtc_time->hour > mSP_GetShopCloseTime()) return; + + if (mSP_SearchItemCategoryPriority(Save_Get(shop).rare_item, + mSP_KIND_FURNITURE, + mSP_LISTTYPE_RARE, game)) { + rare_item = Save_Get(shop).rare_item; + is_rare_item = TRUE; + } else { + int i; + + /* spotlight item in shop wasn't the rare item, so check all + * the goods for one */ + for (i = 0; i < goods_count; i++) { + if (mSP_ItemNo2GoodsListCategory(goods_list[i]) == + mSP_KIND_FURNITURE) { + is_rare_item = mSP_SearchItemCategoryPriority( + goods_list[i], mSP_KIND_FURNITURE, + mSP_LISTTYPE_RARE, game); + + if (is_rare_item != FALSE) { + rare_item = goods_list[i]; + + break; + } + } + } + } + + /* check if a rare item was found, and if so, send the notice + * leaflet to the player */ + if (is_rare_item != FALSE) { + int arrange_idx = mHS_get_arrange_idx(p); + + if (mHS_get_pl_no_detail(arrange_idx) != -1) { + mSP_ShopItsumoChirashi(arrange_idx, shop_level, + rare_item, is_rare_item, + mPO_SENDTYPE_LEAFLET); + mCkRh_SavePlayTime(player_no); + } + } + } +} + +extern void mSP_SetRenewalChiraswhi_AppoDay() { + static int chirashi_idx_appoday[mSP_SHOP_TYPE_NUM] = { 0x1B, 0x1B, 0x1C, 0x1D }; + Mail_c leaflet; + Mail_ct_c* content = &leaflet.content; + int header_back_start; + + if (Save_Get(shop).shop_info.upgrading_today && mEv_CheckEvent(mEv_SAVED_RENEWSHOP) == FALSE) { + int shop_level = mSP_GetRealShopLevel(); + int i; + + for (i = 0; i < mHS_HOUSE_NUM; i++) { + int player_no = mHS_get_pl_no(i) & 3; + int free_mail_idx = mMl_chk_mail_free_space(Save_Get(homes[i]).mailbox, HOME_MAILBOX_SIZE); + + if (free_mail_idx >= 0 && Save_Get(homes[i]).ownerID.land_id != 0xFFFF && mEv_ArbeitPlayer(player_no) == FALSE) { + + mMl_clear_mail(&leaflet); + mHandbill_Load_HandbillFromRom( + content->header, + &header_back_start, + content->footer, + content->body, + chirashi_idx_appoday[shop_level] + ); + leaflet.content.font = mMl_FONT_0; + leaflet.content.header_back_start = header_back_start; + leaflet.content.mail_type = mMl_TYPE_SHOP_SALE_LEAFLET; + leaflet.content.paper_type = ITM_PAPER55; // simple paper + + mPr_CopyPersonalID(&leaflet.header.recipient.personalID, &Save_Get(private[mHS_get_pl_no(i) & 3]).player_ID); + leaflet.header.recipient.type = mMl_NAME_TYPE_PLAYER; + + mMl_copy_mail(Save_Get(homes[i]).mailbox + free_mail_idx, &leaflet); + } + } + + Save_Get(shop).shop_info.upgrading_today = FALSE; + } +} + +extern void mSP_ExchangeLineUp_InGame(GAME* game) { + if (mSP_CheckExchangeDay2()) { + if (mSP_CheckExchangeMonth()) { + mSP_LotteryLineUp_GameAlloc(game); + } + + mSP_NewExchangeDay(); + mSP_ExchangeLineUp_GameAlloc(game); + Save_Get(shop).shop_info.not_loaded_before = TRUE; + mSP_SetShopRareFurnitureChirashi(Common_Get(player_no), Save_Get(shop).items, mSP_GOODS_COUNT, game); + } +} + +extern void mSP_PlusSales(u32 sum) { + Save_Get(shop).sales_sum += sum; + + if (mSP_GetShopLevel() == mSP_SHOP_TYPE_ZAKKA) { + if (Save_Get(shop).sales_sum > mSP_COMBINI_SUM) { + Save_Get(shop).sales_sum = mSP_COMBINI_SUM; + } + } + else if (mSP_GetShopLevel() == mSP_SHOP_TYPE_COMBINI) { + if (Save_Get(shop).sales_sum > mSP_SUPER_SUM) { + Save_Get(shop).sales_sum = mSP_SUPER_SUM; + } + } + else if (mSP_GetShopLevel() == mSP_SHOP_TYPE_SUPER) { + if (Save_Get(shop).sales_sum > mSP_DSUPER_SUM) { + Save_Get(shop).sales_sum = mSP_DSUPER_SUM; + } + } +} + +/* @unused size: 0x74 */ +// extern int mSP_GetVisitorCount() + +extern int mSP_SetNewVisitor() { + if (mLd_PlayerManKindCheck()) { + Save_Get(shop).visitor_flag = TRUE; + return TRUE; + } + + return FALSE; +} + +extern u32 mSP_GetSalesSum() { + return Save_Get(shop).sales_sum; +} + +extern int mSP_GetShopLevel() { + return Save_Get(shop).shop_info.shop_level; +} + +extern int mSP_RenewShopLevel() { + if (Save_Get(shop).shop_info.shop_level != (u8)mSP_GetRealShopLevel()) { + Save_Get(shop).shop_info.shop_level = mSP_GetRealShopLevel(); + return TRUE; + } + + return FALSE; +} + +extern int mSP_GetRealShopLevel() { + u32 sales_sum = mSP_GetSalesSum(); + + if (sales_sum >= mSP_DSUPER_SUM && Save_Get(shop).visitor_flag != FALSE) { + return mSP_SHOP_TYPE_DSUPER; + } + else if (sales_sum >= mSP_SUPER_SUM) { + return mSP_SHOP_TYPE_SUPER; + } + + return sales_sum >= mSP_COMBINI_SUM ? mSP_SHOP_TYPE_COMBINI : mSP_SHOP_TYPE_ZAKKA; +} + +extern int mSP_GetGoodsPercent(int priority) { + int goods_power = mPr_GetGoodsPower(); + + if (priority >= 0 && priority <= mSP_PRIORITY_RARE) { + int rare; + int uncommon; + + if (goods_power < 0) { + uncommon = goods_power + 35 + 5; + rare = 5; + } + else { + rare = goods_power + 5; + uncommon = rare + 35; + } + + switch (priority) { + case mSP_PRIORITY_COMMON: + return 100 - uncommon; + case mSP_PRIORITY_UNCOMMON: + return uncommon - rare; + case mSP_PRIORITY_RARE: + return rare; + default: + return 0; + } + } + else { + return 0; + } +} + +extern void mSP_PrintNowShopSalesSum(gfxprint_t* gfxprint) { + if (mFI_CheckFieldData()) { + int shop_level = mSP_GetShopLevel(); + int status = mSP_ShopOpen(); + u32 sales_sum = mSP_GetSalesSum(); + u32 working_sum; + + switch (shop_level) { + case mSP_SHOP_TYPE_ZAKKA: + working_sum = sales_sum; + break; + case mSP_SHOP_TYPE_COMBINI: + working_sum = sales_sum - mSP_COMBINI_SUM; + break; + case mSP_SHOP_TYPE_SUPER: + working_sum = sales_sum - mSP_SUPER_SUM; + break; + default: + working_sum = sales_sum - mSP_DSUPER_SUM; + break; + } + + gfxprint_color(gfxprint, 200, 200, 250, 255); + gfxprint_locate8x8(gfxprint, 3, 12); + + if (mEv_CheckEvent(mEv_SAVED_RENEWSHOP) == FALSE) { + gfxprint_printf(gfxprint, "%d %d %s", shop_level, working_sum, mSP_ShopStatus2String(status)); + + gfxprint_color(gfxprint, 200, 200, 250, 255); + gfxprint_printf( + gfxprint, + "A%2d,%2d,%2d,%2d,%2d", + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_FURNITURE].a), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_WALLPAPER].a), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CARPET].a), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CLOTH].a), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_PAPER].a) + ); + } + else { + gfxprint_color(gfxprint, 200, 100, 100, 255); + gfxprint_printf( + gfxprint, + "%d %d %s->%d.%d.%d", + shop_level, + working_sum, + mSP_ShopStatus2String(status), + Save_Get(shop).renewal_time.year, + Save_Get(shop).renewal_time.month, + Save_Get(shop).renewal_time.day + ); + + gfxprint_color(gfxprint, 200, 200, 250, 255); + gfxprint_printf( + gfxprint, + " A%2d,%2d,%2d,%2d,%2d", + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_FURNITURE].a), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_WALLPAPER].a), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CARPET].a), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CLOTH].a), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_PAPER].a) + ); + } + + gfxprint_color(gfxprint, 200, 200, 250, 255); + gfxprint_locate8x8(gfxprint, 3, 13); + gfxprint_printf( + gfxprint, + "B%2d,%2d,%2d,%2d,%2d", + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_FURNITURE].b), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_WALLPAPER].b), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CARPET].b), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CLOTH].b), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_PAPER].b) + ); + gfxprint_printf( + gfxprint, + "C%2d,%2d,%2d,%2d,%2d", + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_FURNITURE].c), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_WALLPAPER].c), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CARPET].c), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CLOTH].c), + mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_PAPER].c) + ); + } +} + +extern void mSP_GetGoodsPriority(u8* abc_priorities, int category) { + mSP_goods_priority_list_c* priorities = Save_Get(shop).priority_lists; + + if (category == mSP_KIND_DIARY) { + category = mSP_KIND_FURNITURE; + } + + abc_priorities[0] = priorities[category].a; + abc_priorities[1] = priorities[category].b; + abc_priorities[2] = priorities[category].c; +} + +static void mSP_SetExchangeDay() { + Save_Get(shop).exchange_time = Common_Get(time.rtc_time); +} + +static void mSP_InitGoods() { + Shop_c* shop = Save_GetPointer(shop); + mActor_name_t* items = shop->items; + int i; + + for (i = 0; i < mSP_GOODS_COUNT; i++) { + *items++ = EMPTY_NO; + } +} + +extern void mSP_ExchangeLineUp_ZeldaMalloc() { + mSP_InitGoods(); + mSP_MakeGoodsList(NULL); + mSP_SetExchangeDay(); +} + +extern void mSP_LotteryLineUp_ZeldaMalloc() { + mSP_MakeLotteryList(NULL); +} + +extern void mSP_ExchangeLineUp_GameAlloc(GAME* game) { + mSP_InitGoods(); + mSP_MakeGoodsList(game); + mSP_SetExchangeDay(); +} + +extern void mSP_LotteryLineUp_GameAlloc(GAME* game) { + mSP_MakeLotteryList(game); +} + +extern void mSP_InitShopSaveData() { + Shop_c* shop = Save_GetPointer(shop); + PersonalID_c* pid = shop->unused_ids; + mActor_name_t* lottery_items = shop->lottery_items; + int i = 0; + + while (i < mSP_PERSONAL_ID_COUNT) { + mPr_ClearPersonalID(pid); + pid++; + i++; + } + + mSP_InitGoods(); + Save_Get(shop).rare_item = EMPTY_NO; + + for (i = 0; i < mSP_LOTTERY_ITEM_COUNT; i++) { + lottery_items[0] = EMPTY_NO; + lottery_items++; + } + + Save_Get(shop).flowers_candy_grab_bag_count = 0; + shop->sales_sum = 0; + shop->exchange_time = Common_Get(time.rtc_time); + shop->exchange_time.month--; + shop->shop_info.shop_level = mSP_SHOP_TYPE_ZAKKA; + shop->renewal_time = shop->exchange_time; + shop->shop_info.upgrading_today = FALSE; + Save_Get(shop).visitor_flag = FALSE; +} + +static void mSP_DecideUniqueCommonList(mSP_goods_priority_list_c* priority_list) { + static mSP_goods_priority_list_c priority_candidate[6] = { + { mSP_PRIORITY_COMMON, mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_RARE, 0 }, + { mSP_PRIORITY_COMMON, mSP_PRIORITY_RARE, mSP_PRIORITY_UNCOMMON, 0 }, + { mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_COMMON, mSP_PRIORITY_RARE, 0 }, + { mSP_PRIORITY_RARE, mSP_PRIORITY_COMMON, mSP_PRIORITY_UNCOMMON, 0 }, + { mSP_PRIORITY_RARE, mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_COMMON, 0 }, + { mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_RARE, mSP_PRIORITY_COMMON, 0 } + }; + + priority_list[0] = priority_candidate[RANDOM(6)]; +} + +static void mSP_DecideGoodsCommonList() { + mSP_goods_priority_list_c* priority_lists = Save_Get(shop).priority_lists; + + mSP_DecideUniqueCommonList(&priority_lists[mSP_KIND_FURNITURE]); + mSP_DecideUniqueCommonList(&priority_lists[mSP_KIND_PAPER]); + mSP_DecideUniqueCommonList(&priority_lists[mSP_KIND_CLOTH]); + mSP_DecideUniqueCommonList(&priority_lists[mSP_KIND_CARPET]); + mSP_DecideUniqueCommonList(&priority_lists[mSP_KIND_WALLPAPER]); +} + +extern void mSP_ShopGameStartCt(GAME* game) { + mSP_DecideGoodsCommonList(); + mSP_InitShopSaveData(); + mSP_ExchangeLineUp_InGame(game); +} + +extern mActor_name_t mSP_GetNowShopBgNum() { + switch (Save_Get(scene_no)) { + case SCENE_SHOP0: + { + if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) { + return 0xFA; + } + + return 0xF8; + } + + case SCENE_CONVENI: + { + if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) { + return 0xFB; + } + + return 0xFE; + } + + case SCENE_SUPER: + { + if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) { + return 0xFC; + } + + return 0x102; + } + + case SCENE_DEPART: + { + if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) { + return 0xFD; + } + + return 0x100; + } + + case SCENE_DEPART_2: + return 0x101; + + default: + return 0xFE; + } +} + +static int mSP_what_special_sale; + +extern int mSP_WhatSpecialSale() { + return mSP_what_special_sale; +} + +extern mActor_name_t mSP_GetNowShopFgNum() { + int event_kind = Save_Get(event_save_data).special.event.bargin.kind; + + switch (Save_Get(scene_no)) { + case SCENE_SHOP0: + { + if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_EVENT) { + if (event_kind == mSP_KIND_FURNITURE) { + mSP_what_special_sale = mSP_KIND_FURNITURE; + return 0x163; + } + + if (event_kind == mSP_KIND_CLOTH) { + mSP_what_special_sale = mSP_KIND_CLOTH; + return 0x166; + } + + if (event_kind == mSP_KIND_WALLPAPER) { + mSP_what_special_sale = mSP_KIND_WALLPAPER; + return 0x165; + } + + mSP_what_special_sale = mSP_KIND_CARPET; + return 0x164; + } + + if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) { + return 0x14D; + } + + return 0x22; + } + + case SCENE_CONVENI: + { + if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_EVENT) { + if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_FURNITURE) { + mSP_what_special_sale = mSP_KIND_FURNITURE; + return 0x167; + } + + if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_CLOTH) { + mSP_what_special_sale = mSP_KIND_CLOTH; + return 0x16A; + } + + if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_WALLPAPER) { + mSP_what_special_sale = mSP_KIND_WALLPAPER; + return 0x169; + } + + mSP_what_special_sale = mSP_KIND_CARPET; + return 0x168; + } + + if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) { + return 0x14E; + } + + return 0x23; + } + + case SCENE_SUPER: + { + if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_EVENT) { + if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_FURNITURE) { + mSP_what_special_sale = mSP_KIND_FURNITURE; + return 0x16B; + } + + if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_CLOTH) { + mSP_what_special_sale = mSP_KIND_CLOTH; + return 0x16E; + } + + if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_WALLPAPER) { + mSP_what_special_sale = mSP_KIND_WALLPAPER; + return 0x16D; + } + + mSP_what_special_sale = mSP_KIND_CARPET; + return 0x16C; + } + + if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) { + return 0x14F; + } + + return 0x24; + } + + case SCENE_DEPART: + { + if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_EVENT) { + return 0x16F; + } + + if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) { + return 0x150; + } + + return 0x25; + } + + case SCENE_DEPART_2: + { + if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_EVENT) { + if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_FURNITURE) { + mSP_what_special_sale = mSP_KIND_FURNITURE; + return 0x170; + } + + if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_CLOTH) { + mSP_what_special_sale = mSP_KIND_CLOTH; + return 0x173; + } + + if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_WALLPAPER) { + mSP_what_special_sale = mSP_KIND_WALLPAPER; + return 0x172; + } + + mSP_what_special_sale = mSP_KIND_CARPET; + return 0x171; + } + + return 0x26; + } + + default: + return 0x25; + } +} + +extern lbRTC_hour_t mSP_GetShopOpenTime() { + static lbRTC_hour_t shop_open_time_table[mSP_SHOP_TYPE_NUM] = { + 9, + 7, + 9, + 9 + }; + + int shop_level = mSP_GetShopLevel(); + + if (Common_Get(time.rtc_time).day == lbRTC_GetDaysByMonth(Common_Get(time.rtc_time).year, Common_Get(time.rtc_time).month)) { + return 10; // lottery starts at 10AM + } + else { + return shop_open_time_table[shop_level]; + } +} + +extern lbRTC_hour_t mSP_GetShopCloseTime() { + static lbRTC_hour_t shop_close_time_table[mSP_SHOP_TYPE_NUM] = { + 22, + 23, + 22, + 22 + }; + + return shop_close_time_table[mSP_GetShopLevel()]; +} + +extern lbRTC_hour_t mSP_GetShopCloseTime_Bgm() { + static lbRTC_hour_t shop_close_time_table[mSP_SHOP_TYPE_NUM] = { + 22, + 23, + 22, + 22 + }; + + return shop_close_time_table[mSP_GetShopLevel()]; +} + +extern int mSP_InRenewal() { + if (mEv_CheckEvent(mEv_SAVED_RENEWSHOP) == TRUE) { + lbRTC_time_c renew_time = Save_Get(shop).renewal_time; + lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time); + + lbRTC_Sub_DD(&renew_time, 1); + + if ( + lbRTC_IsOverTime(&renew_time, rtc_time) == lbRTC_OVER || + lbRTC_IsEqualTime(rtc_time, &renew_time, lbRTC_CHECK_YEARS | lbRTC_CHECK_MONTHS | lbRTC_CHECK_DAYS) != FALSE + ) { + return TRUE; + } + } + + return FALSE; +} + +/* @unused size: 0xF0 */ +// int mSP_CheckSpecialSalesSoldOut(...) + +extern int mSP_ShopOpen() { + lbRTC_time_c rtc_time = Common_Get(time.rtc_time); + lbRTC_hour_t now_hour; + + if (mEv_CheckFirstJob()) { + return mSP_SHOP_STATUS_OPEN; // shop is forcefully open during chores + } + + if (mEv_CheckEvent(mEv_SPNPC_SHOP) == TRUE) { + lbRTC_time_c bargin_time = Save_Get(event_save_data).special.event.bargin.start_time; + + if (bargin_time.day == rtc_time.day) { + lbRTC_time_c end_time = Save_Get(event_save_data).special.event.bargin.end_time; + lbRTC_time_c start_time_pre = bargin_time; + lbRTC_time_c end_time_post = end_time; + now_hour = rtc_time.hour; + + lbRTC_Sub_hh(&start_time_pre, 1); + lbRTC_Add_hh(&end_time_post, 1); + + if (now_hour >= mTM_FIELD_RENEW_HOUR && now_hour < mSP_GetShopOpenTime()) { + return mSP_SHOP_STATUS_PRE; + } + + if (now_hour < mTM_FIELD_RENEW_HOUR || now_hour >= mSP_GetShopCloseTime()) { + return mSP_SHOP_STATUS_END; + } + + if (lbRTC_IsOverTime(&start_time_pre, &rtc_time) == lbRTC_LESS) { + return mSP_SHOP_STATUS_OPEN; + } + + if (lbRTC_IsOverTime(&bargin_time, &rtc_time) == lbRTC_LESS) { + return mSP_SHOP_STATUS_PREEVENT; + } + + if (lbRTC_IsOverTime(&end_time, &rtc_time) == lbRTC_LESS) { + return mSP_SHOP_STATUS_OPENEVENT; + } + + if (lbRTC_IsOverTime(&end_time_post, &rtc_time) == lbRTC_LESS) { + return mSP_SHOP_STATUS_ENDEVENT; + } + + return mSP_SHOP_STATUS_OPEN; + } + } + + now_hour = rtc_time.hour; + + if (mSP_InRenewal() != FALSE) { + return mSP_SHOP_STATUS_RENEW; + } + + if (now_hour >= mSP_GetShopOpenTime() && now_hour < mSP_GetShopCloseTime()) { + return mSP_SHOP_STATUS_OPEN; + } + + if (now_hour >= mTM_FIELD_RENEW_HOUR && now_hour < mSP_GetShopOpenTime()) { + return mSP_SHOP_STATUS_PRE; + } + + return mSP_SHOP_STATUS_END; +} + +extern void mSP_RandomHaniwaSelect(mActor_name_t* haniwa_list, int count) { + int i; + + for (i = 0; i < count; i++) { + haniwa_list[i] = EMPTY_NO; + } + + for (i = 0; i < count; i++) { + int set = FALSE; + + while (!set) { + mActor_name_t haniwa = HANIWA_START + (mActor_name_t)FTR_NO_2_IDX(RANDOM(HANIWA_NUM)); + + if (mSP_GoodsExistAlready(haniwa_list, count, haniwa) == FALSE) { + haniwa_list[i] = haniwa; + set = TRUE; + } + else if (count > HANIWA_NUM) { + haniwa_list[i] = haniwa; + set = TRUE; + } + } + } +} + +extern void mSP_RandomMDSelect(mActor_name_t* md_list, int count) { + int i; + + for (i = 0; i < count; i++) { + md_list[i] = EMPTY_NO; + } + + for (i = 0; i < count; i++) { + int set = FALSE; + + while (!set) { + mActor_name_t md = ITM_MINIDISK_START + RANDOM(NOT_SECRET_MD_NUM); + + if (mSP_GoodsExistAlready(md_list, count, md) == FALSE) { + md_list[i] = md; + set = TRUE; + } + else if (count > NOT_SECRET_MD_NUM) { + md_list[i] = md; + set = TRUE; + } + } + } +} + +extern void mSP_RandomUmbSelect(mActor_name_t* umb_list, int count) { + int i; + + for (i = 0; i < count; i++) { + umb_list[i] = EMPTY_NO; + } + + for (i = 0; i < count; i++) { + int set = FALSE; + + while (!set) { + mActor_name_t umb = ITM_GELATO_UMBRELLA + RANDOM(UMBRELLA_NUM); + + if (mSP_GoodsExistAlready(umb_list, count, umb) == FALSE) { + umb_list[i] = umb; + set = TRUE; + } + else if (count > UMBRELLA_NUM) { + umb_list[i] = umb; + set = TRUE; + } + } + } +} + +static int mSP_CountBirth(u8 birth_type) { + int count = 0; + u8* birth_type_p = mRmTp_CheckFtrBirthInfoTop(); + int i; + + for (i = 0; i < FTR_NUM; i++) { + if (birth_type_p[0] == birth_type) { + count++; + } + + birth_type_p++; + } + + return count; +} + +static mActor_name_t mSP_FtrBirthIdx2ItemNo(u8 birth_type, int birth_idx) { + int count = 0; + u8* birth_type_p = mRmTp_CheckFtrBirthInfoTop(); + int i; + + for (i = 0; i < FTR_NUM; i++) { + if (birth_type_p[0] == birth_type) { + if (count == birth_idx) { + return mRmTp_FtrIdx2FtrItemNo(i, mRmTp_DIRECT_SOUTH); + } + + count++; + } + + birth_type_p++; + } + + return FTR_DINO_TREX_SKULL; +} + +extern mActor_name_t mSP_RandomOneFossilSelect(int multi_fossil) { + u8 birth_type = multi_fossil == FALSE ? mRmTp_BIRTH_TYPE_SINGLE_FOSSIL : mRmTp_BIRTH_TYPE_MULTI_FOSSIL; + int count = mSP_CountBirth(birth_type); + + return mSP_FtrBirthIdx2ItemNo(birth_type, RANDOM(count)); +} + +extern int mSP_Chk_HukubukuroSail() { + lbRTC_time_c rtc_time = Common_Get(time.rtc_time); + lbRTC_year_t year = rtc_time.year; + lbRTC_month_t month = rtc_time.month; + lbRTC_day_t day = rtc_time.day; + + if (month == lbRTC_NOVEMBER) { + int black_friday = lbRTC_Weekly_day(year, lbRTC_NOVEMBER, 4, lbRTC_THURSDAY) + 1; + + if (black_friday == day) { + return TRUE; + } + } + + return FALSE; +} + +extern int mSP_CheckFukubikiDay() { + lbRTC_time_c rtc_time = Common_Get(time.rtc_time); + lbRTC_year_t year = rtc_time.year; + lbRTC_month_t month = rtc_time.month; + lbRTC_day_t day = rtc_time.day; + lbRTC_day_t days_in_month = lbRTC_GetDaysByMonth(year, month); + + return days_in_month == day; +} + +extern int mSP_SetGoods2ReservedPoint(mActor_name_t goods, mActor_name_t reserved_no) { + mActor_name_t* shop_fg = mFI_BkNumtoUtFGTop(0, 0); + int i; + + for (i = 0; i < UT_TOTAL_NUM; i++) { + if (reserved_no == shop_fg[0]) { + mFI_UtNumtoFGSet_common(goods, i % UT_X_NUM, i / UT_X_NUM, FALSE); + return TRUE; + } + + shop_fg++; + } + + return FALSE; +} + +extern int mSP_CheckHallowinDay() { + int res = FALSE; + lbRTC_time_c rtc_time = Common_Get(time.rtc_time); + lbRTC_month_t month = rtc_time.month; + lbRTC_day_t day = rtc_time.day; + + if ( + month == lbRTC_OCTOBER && + day >= 16 && + day <= 30 + ) { + res = TRUE; + } + + return res; +} + +extern void mSP_SetTanukiShopStatus() { + if (mSP_ShopOpen() == mSP_SHOP_STATUS_OPENEVENT) { + Common_Set(tanuki_shop_status, mSP_TANUKI_SHOP_STATUS_EVENT); + } + else if (mSP_CheckFukubikiDay()) { + Common_Set(tanuki_shop_status, mSP_TANUKI_SHOP_STATUS_FUKUBIKI); + } + else if (mSP_Chk_HukubukuroSail()) { + Common_Set(tanuki_shop_status, mSP_TANUKI_SHOP_STATUS_HUKUBUKURO_SALE); + } + else if (mSP_CheckHallowinDay()) { + Common_Set(tanuki_shop_status, mSP_TANUKI_SHOP_STATUS_HALLOWEEN); + } + else { + Common_Set(tanuki_shop_status, mSP_TANUKI_SHOP_STATUS_NORMAL); + } +} + +static u32 mSP_sack_amount[MONEY_NUM] = { + 100, + 1000, + 10000, + 30000 +}; + +static mActor_name_t mSP_itemNo[MONEY_NUM] = { + ITM_MONEY_100, + ITM_MONEY_1000, + ITM_MONEY_10000, + ITM_MONEY_30000 +}; + +extern int mSP_money_check(u32 amount) { + u32 money = Common_Get(now_private)->inventory.wallet; + int res = FALSE; + + if (money < amount) { + int i; + + for (i = 0; i < MONEY_NUM; i++) { + int sack_num = mPr_GetPossessionItemSumWithCond(Common_Get(now_private), mSP_itemNo[i], mPr_ITEM_COND_NORMAL); + + money += sack_num * mSP_sack_amount[i]; + if (money >= amount) { + res = TRUE; + break; + } + } + } + else { + res = TRUE; + } + + return res; +} + +static u32 mSP_get_sell_price_sub(u32 money, u32 amount) { + u32 sack_num; + int i; + + for (i = 0; i < MONEY_NUM; i++) { + for (sack_num = mPr_GetPossessionItemSumWithCond(Common_Get(now_private), mSP_itemNo[i], mPr_ITEM_COND_NORMAL); sack_num != 0; sack_num--) { + int sack_idx = mPr_GetPossessionItemIdxWithCond(Common_Get(now_private), mSP_itemNo[i], mPr_ITEM_COND_NORMAL); + + mPr_SetPossessionItem(Common_Get(now_private), sack_idx, EMPTY_NO, mPr_ITEM_COND_NORMAL); + money += mSP_sack_amount[i]; + + if (money >= amount) { + return money - amount; + } + } + } + + return 0; +} + +extern void mSP_get_sell_price(u32 amount) { + u32 money = Common_Get(now_private)->inventory.wallet; + + if (money < amount) { + money = mSP_get_sell_price_sub(money, amount); + } + else { + money -= amount; + } + + Common_Get(now_private)->inventory.wallet = money; +} + +static int mSP_GetNonePossessionItemCount_InList(mActor_name_t* list, int category, u32* collect_bitfield) { + mActor_name_t* list_p; + + if (list != NULL) { + int count = 0; + + for (list_p = list; list_p[0] != EMPTY_NO; list_p++) { + int collect_idx; + + if (category == mSP_KIND_FURNITURE) { + collect_idx = mRmTp_FtrItemNo2FtrIdx(list_p[0]); + } + else if (category == mSP_KIND_CARPET) { + collect_idx = list_p[0] - ITM_CARPET_START; + } + else { + collect_idx = list_p[0] - ITM_WALL_START; + } + + if (((collect_bitfield[collect_idx >> 5] >> (collect_idx & 0x1F)) & 1) == 0) { + count++; + } + } + + return count; + } + + return 0; +} + +static mActor_name_t mSP_GetNonePossessionItem_InList(mActor_name_t* list, int category, u32* collect_bitfield) { + int none_count = mSP_GetNonePossessionItemCount_InList(list, category, collect_bitfield); + + if (none_count != 0 && list != NULL) { + int selected_idx = RANDOM(none_count); + mActor_name_t* list_p; + int count = 0; + + for (list_p = list; list_p[0] != EMPTY_NO; list_p++) { + int collect_idx; + + if (category == mSP_KIND_FURNITURE) { + collect_idx = mRmTp_FtrItemNo2FtrIdx(list_p[0]); + } + else if (category == mSP_KIND_CARPET) { + collect_idx = list_p[0] - ITM_CARPET_START; + } + else { + collect_idx = list_p[0] - ITM_WALL_START; + } + + if (((collect_bitfield[collect_idx >> 5] >> (collect_idx & 0x1F)) & 1) == 0) { + if (selected_idx == count) { + return list_p[0]; + } + else { + count++; + } + } + } + } + + return EMPTY_NO; +} + +static mActor_name_t mSP_GetNonePossessionItem_InLotteryFurniture(int player_no) { + return mSP_GetNonePossessionItem_InList( + mSP_ftr_list[mSP_LIST_LOTTERY], + mSP_KIND_FURNITURE, + (player_no >= 0 && player_no < PLAYER_NUM) ? + Save_Get(private[player_no]).furniture_collected_bitfield : + Common_Get(now_private)->furniture_collected_bitfield + ); +} + +static mActor_name_t mSP_GetNonePossessionItem_InEventFurniture(int player_no) { + return mSP_GetNonePossessionItem_InList( + mSP_ftr_list[mSP_LIST_EVENT], + mSP_KIND_FURNITURE, + (player_no >= 0 && player_no < PLAYER_NUM) ? + Save_Get(private[player_no]).furniture_collected_bitfield : + Common_Get(now_private)->furniture_collected_bitfield + ); +} + +/* @fabricated @unused */ +static mActor_name_t mSP_GetNonePossessionItem_InEventWall(int player_no) { + return mSP_GetNonePossessionItem_InList( + mSP_ftr_list[mSP_LIST_EVENT], + mSP_KIND_WALLPAPER, + (player_no >= 0 && player_no < PLAYER_NUM) ? + Save_Get(private[player_no]).wall_collected_bitfield : + Common_Get(now_private)->wall_collected_bitfield + ); +} + +/* @fabricated @unused */ +static mActor_name_t mSP_GetNonePossessionItem_InEventCarpet(int player_no) { + return mSP_GetNonePossessionItem_InList( + mSP_ftr_list[mSP_LIST_EVENT], + mSP_KIND_CARPET, + (player_no >= 0 && player_no < PLAYER_NUM) ? + Save_Get(private[player_no]).carpet_collected_bitfield : + Common_Get(now_private)->carpet_collected_bitfield + ); +} + +/* @fabricated @unused */ +static mActor_name_t mSP_GetNonePossessionItem_InABCFurniture(int player_no) { + // TODO: check this impl is right using func size -- they probably did the list calc in this func itself + u8 abc_priorities[3]; + + mSP_GetGoodsPriority(abc_priorities, mSP_KIND_FURNITURE); + + return mSP_GetNonePossessionItem_InList( + mSP_GetItemList(mSP_ftr_list, abc_priorities, mSP_LISTTYPE_ABC), + mSP_KIND_FURNITURE, + (player_no >= 0 && player_no < PLAYER_NUM) ? + Save_Get(private[player_no]).furniture_collected_bitfield : + Common_Get(now_private)->furniture_collected_bitfield + ); +} + +typedef mActor_name_t (*mSP_GET_NONE_POSSESSION_ITEM_PROC)(int); + +static mActor_name_t mSP_CarryOutAlternativeRandomSelect(mSP_GET_NONE_POSSESSION_ITEM_PROC proc0, mSP_GET_NONE_POSSESSION_ITEM_PROC proc1, int player_no) { + int rng = RANDOM(100); + + if ((rng & 1)) { + mActor_name_t item = (*proc0)(player_no); + + if (item == EMPTY_NO) { + item = (*proc1)(player_no); + + if (item != EMPTY_NO) { + return item; + } + } + else { + return item; + } + } + else { + mActor_name_t item = (*proc1)(player_no); + + if (item == EMPTY_NO) { + item = (*proc0)(player_no); + + if (item != EMPTY_NO) { + return item; + } + } + else { + return item; + } + } + + return EMPTY_NO; +} + +static mActor_name_t mSP_CarryOutAlternativeRandomSelect_NoneNULL(int category0, int list0, int category1, int list1) { + int rng = RANDOM(100); + mActor_name_t item; + + if ((rng & 1)) { + mSP_SelectRandomItem_New(NULL, &item, 1, NULL, 0, category0, list0, FALSE); + return item; + } + else { + mSP_SelectRandomItem_New(NULL, &item, 1, NULL, 0, category1, list1, FALSE); + return item; + } +} + +/* @unused size: 0xB8 */ +// extern mActor_name_t mSP_SelectNpcBirthdayPresent(...) +static void mSP_SelectNpcBirthdayPresent() { + // necessary to include for data + static int priority[6][3] = { + { mSP_PRIORITY_COMMON, mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_RARE }, + { mSP_PRIORITY_COMMON, mSP_PRIORITY_RARE, mSP_PRIORITY_RARE }, // lol based on this, I think it should've been common, rare, uncommon + { mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_COMMON, mSP_PRIORITY_RARE }, + { mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_RARE, mSP_PRIORITY_COMMON }, + { mSP_PRIORITY_RARE, mSP_PRIORITY_COMMON, mSP_PRIORITY_UNCOMMON }, + { mSP_PRIORITY_RARE, mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_COMMON } + }; +} + +extern mActor_name_t mSP_SelectFishginPresent(int player_no) { + mActor_name_t item = mSP_CarryOutAlternativeRandomSelect(&mSP_GetNonePossessionItem_InLotteryFurniture, &mSP_GetNonePossessionItem_InEventFurniture, player_no); + + if (item != EMPTY_NO) { + return item; + } + + return mSP_CarryOutAlternativeRandomSelect_NoneNULL(mSP_KIND_FURNITURE, mSP_LISTTYPE_LOTTERY, mSP_KIND_FURNITURE, mSP_LISTTYPE_EVENT); +} + +mActor_name_t mSP_gc_famicom_table[8] = { + FTR_FAMICOM_CLU_CLU_LAND, + FTR_FAMICOM_BALLOON_FIGHT, + FTR_FAMICOM_DONKEY_KONG, + FTR_FAMICOM_DK_JR_MATCH, + FTR_FAMICOM_PINBALL, + FTR_FAMICOM_TENNIS, + FTR_FAMICOM_GOLF, + FTR_FAMICOM_EXCITEBIKE +}; + +/* @unused size: 0xDC */ +// static mActor_name_t mSP_RandomOneFamicomSelect(...) + +static mActor_name_t mSP_AGBRandomFamicomSelect() { + mActor_name_t item = EMPTY_NO; + + mSP_SelectRandomItem_New(NULL, &item, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_ISLANDFAMICOM, FALSE); + return item; +} + +static mActor_name_t mSP_GetRandomTrash() { + static mActor_name_t trash_table[3] = { ITM_DUST0_EMPTY_CAN, ITM_DUST1_BOOT, ITM_DUST2_OLD_TIRE }; + + return trash_table[RANDOM(3)]; +} + +static void mSP_SelectRandomItemToAGB_Unit(mActor_name_t* item, xyz_t* wpos, int ut_x, int ut_z) { + switch (item[0]) { + case 0xFEB2: + { + item[0] = mSP_GetRandomTrash(); + break; + } + + case 0xFEA1: + { + mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_COMMON, FALSE); + break; + } + + case 0xFEA2: + { + mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_RARE, FALSE); + break; + } + + case 0xFEA3: + { + if ((RANDOM(10) & 1)) { + mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_EVENT, FALSE); + } + else { + mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_LOTTERY, FALSE); + } + + break; + } + + case 0xFEA5: + { + mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_ISLAND, FALSE); + break; + } + + case 0xFEA4: + { + item[0] = mSP_AGBRandomFamicomSelect(); + break; + } + + case 0xFEA9: + { + mSP_RandomUmbSelect(item, 1); + break; + } + + case 0xFEA6: + { + item[0] = mSP_RandomOneFossilSelect((RANDOM(4) & 1)); + break; + } + + case 0xFEA7: + { + mSP_RandomMDSelect(item, 1); + break; + } + + case 0xFEA8: + { + mSP_RandomHaniwaSelect(item, 1); + break; + } + + case 0xFEAA: + { + mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_CARPET, mSP_LISTTYPE_COMMON, FALSE); + break; + } + + case 0xFEAB: + { + mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_CARPET, mSP_LISTTYPE_RARE, FALSE); + break; + } + + case 0xFEAC: + { + mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_WALLPAPER, mSP_LISTTYPE_COMMON, FALSE); + break; + } + + case 0xFEAD: + { + mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_WALLPAPER, mSP_LISTTYPE_RARE, FALSE); + break; + } + + case 0xFEAE: + { + mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_CLOTH, mSP_LISTTYPE_COMMON, FALSE); + break; + } + + case 0xFEAF: + { + mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_CLOTH, mSP_LISTTYPE_RARE, FALSE); + break; + } + + case 0xFEB0: + { + int hole_no = mCoBG_GetHoleNumber(*wpos); + + if (hole_no != -1) { + item[0] = HOLE_START + (mActor_name_t)hole_no; + } + else { + item[0] = EMPTY_NO; + } + + break; + } + + case 0xFEB1: + { + item[0] = ITM_WHITE_PANSY_BAG + RANDOM(FLOWER_NUM); + break; + } + + case ITM_KABU_10: + case ITM_KABU_50: + case ITM_KABU_100: + { + item[0] = ITM_KABU_SPOILED; // spoil any turnips + break; + } + + case 0xF11F: + { + item[0] = ACTOR_PROP_VILLAGER_SIGNBOARD; + break; + } + } +} + +#ifndef MUST_MATCH +/* @nonmatching - minor float load/store issue with xyz_t.z & weird scheduling issue */ +extern void mSP_SelectRandomItemToAGB() { + int i; + int ut_x; + int ut_z; + xyz_t* wpos_p; + mActor_name_t* start_p; + mActor_name_t* item_p; + f32 x_pos; + + xyz_t wpos = { 0.0f, 0.0f, 0.0f }; + int bx = 0; + int bz = 0; + + mFI_BlockKind2BkNum(&bx, &bz, mRF_BLOCKKIND_ISLAND_LEFT); + + /* convert all unit island items to valid items */ + for (i = 0; i < mISL_FG_BLOCK_X_NUM; i++) { + item_p = &Save_Get(island).fgblock[0][i].items[0][0]; + + mFI_BkNum2WposXZ(&wpos.x, &wpos.z, bx + i, bz); + wpos.x += mFI_UT_WORLDSIZE_HALF_X_F; + wpos.z += mFI_UT_WORLDSIZE_HALF_Z_F; + x_pos = wpos.x; + + for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) { + wpos.x = x_pos; + + for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) { + // this matches instructions but out of order and wrong registers + mSP_SelectRandomItemToAGB_Unit(item_p, &wpos, ut_x, ut_z); + wpos.x += mFI_UT_WORLDSIZE_X_F; + item_p++; + } + + wpos.z += mFI_UT_WORLDSIZE_Z_F; + } + } + + /* add correctly placed signboard actor */ + for (i = 0; i < mISL_FG_BLOCK_X_NUM; i++) { + start_p = &Save_Get(island).fgblock[0][i].items[0][0]; + item_p = &Save_Get(island).fgblock[0][i].items[0][0]; + + for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) { + for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) { + if (item_p[0] == COTTAGE_NPC) { + start_p[((ut_x - 1) & 15) + (((ut_z + 1) & 0xF) << 4)] = ACTOR_PROP_VILLAGER_SIGNBOARD; + } + + item_p++; + } + } + } + + /* remove incorrectly placed signboard actors */ + for (i = 0; i < mISL_FG_BLOCK_X_NUM; i++) { + start_p = &Save_Get(island).fgblock[0][i].items[0][0]; + item_p = &Save_Get(island).fgblock[0][i].items[0][0]; + + for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) { + for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) { + if (item_p[0] == ACTOR_PROP_VILLAGER_SIGNBOARD && start_p[((ut_x + 1) & 15) + (((ut_z - 1) & 0xF) << 4)] != COTTAGE_NPC) { + item_p[0] = EMPTY_NO; + } + + item_p++; + } + } + } +} +#else +const xyz_t lbl_806432b4 = {0.0f, 0.0f, 0.0f}; +REL_SYMBOL_AT(lbl_806432b4, 0x806432b4) + +#include "orderfloats/806432c0_806432c8.inc" + +extern asm void mSP_SelectRandomItemToAGB() { + #include "asm/803ebb44.s" +} +#endif + +extern const char* mSP_ShopStatus2String(int status) { + static char dummy[] = "hahaha"; + + static char* str_table[mSP_SHOP_STATUS_NUM] = { + "Pre", + "End", + "Opn", + "Rnw", + "PreEv", + "EndEv", + "OpnEv" + }; + + if (status >= 0 && status < mSP_SHOP_STATUS_NUM) { + return str_table[status]; + } + + return dummy; +} + +extern mActor_name_t mSP_GetRandomStationToyItemNo() { + /* TODO: where does this go? DnM+ indicates no unused functions after this, but data appears after str_table in mSP_ShopStatus2String */ + static mActor_name_t train[2] = { + FTR_LOCOMOTIVE_MODEL, FTR_TRAIN_CAR_MODEL + }; + + /* TODO: furniture item index enum/defines */ + return mRmTp_FtrIdx2FtrItemNo(0x42A + RANDOM(15), mRmTp_DIRECT_SOUTH); +} + +#include "../rel/m_item_debug.c" diff --git a/rel/m_watch_my_step.c b/rel/m_watch_my_step.c index a70085a8..b3947350 100644 --- a/rel/m_watch_my_step.c +++ b/rel/m_watch_my_step.c @@ -493,7 +493,7 @@ static void mWt_mybell_confirmation_move(GAME_PLAY* play) { } } - if ((u32)i == 8 || mEv_CheckFirstJob() == TRUE || (i <= 4 && Common_Get(nook_shop_state) == 3)) { // TODO: shop state enum, this is likely raffle + if ((u32)i == 8 || mEv_CheckFirstJob() == TRUE || (i <= 4 && Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI)) { if (S_mybell_conf.update_money == TRUE) { S_mybell_conf.all_money = get_all_money(); mWt_set_coin_se(FALSE);