Implement and link m_cockroach, m_police_box

This commit is contained in:
Cuyler36
2023-04-29 02:01:44 -04:00
parent a6e215e882
commit 5f3a6f1f5b
12 changed files with 917 additions and 10 deletions
+6
View File
@@ -1,5 +1,7 @@
sys_vimgr.c:
.text: [0x803703F8, 0x80370418]
m_cockroach.c:
.text: [0x80385430, 0x80385A80]
m_debug_hayakawa.c:
.text: [0x803965E4, 0x803973E8]
.rodata: [0x80641D50, 0x80641D90]
@@ -21,6 +23,10 @@ m_malloc.c:
#m_lib.c: #sqrtf statics
# .text: [0x803BAB0C, 0x803BB960]
# .rodata: [0x80642640, 0x80642680]
m_police_box.c:
.text: [0x803DE8A0, 0x803DEE38]
.rodata: [0x806431C8, 0x806431D8]
.data: [0x8065BE98, 0x8065BEF0]
m_room_type/mRmTp_FtrItemNo2FtrIdx.c:
.text: [0x803E7878, 0x803E78BC]
#m_time.c: # unlinked until function callers that reorder local static variables are implemented.
+17
View File
@@ -8,8 +8,25 @@
extern "C" {
#endif
#define mCkRh_MAX_NUM 10 /* maximum 'stored' in the house */
#define mCkRh_INTERVAL_DAYS 6 /* number of days before roaches will spawn */
#define mCkRh_CAN_LOOK_GOKI_NUM 3 /* maximum that can spawn in the house at once */
extern void mCkRh_InitGokiSaveData_InitNewPlayer();
extern void mCkRh_InitGokiSaveData_1Room(int home_no);
extern void mCkRh_InitGokiSaveData_1Room_ByHomeData(mHm_hs_c* home);
extern void mCkRh_InitGokiSaveData_IslandPlayerRoom();
extern void mCkRh_InitGokiSaveData_AllRoom();
extern void mCkRh_SetGoingOutCottageTime(int scene_id);
extern void mCkRh_SavePlayTime(int player_no);
extern void mCkRh_DecideNowGokiFamilyCount(int player_no);
extern int mCkRh_PlussGokiN_NowRoom(int count, int scene_no);
extern int mCkRh_MinusGokiN_NowRoom(int count, int scene_id);
extern int mCkRh_NowSceneGokiFamilyCount();
extern void mCkRh_InitCanLookGokiCount();
extern int mCkRh_CalcCanLookGokiCount(int count);
extern int mCkRh_GetCanLookGokiCount();
#ifdef __cplusplus
}
+4
View File
@@ -94,6 +94,7 @@ typedef union save_u {
u8 raw[0x26000]; /* Temp to force length */
} Save;
/* sizeof(common_data_t) == 0x2DC00 */
typedef struct common_data_s {
/* 0x000000 */ Save save;
/* 0x026000 */ u8 game_started;
@@ -109,6 +110,9 @@ typedef struct common_data_s {
/* 0x026144 */ u8 tmp0[0x23E8];
/* 0x02852C */ s16 money_power;
/* 0x02852E */ s16 goods_power;
/* 0x028530 */ u8 tmp1[0x5680];
/* 0x02DBB0 */ s16 can_look_goki_count;
/* 0x02DBB2 */ u8 tmp2[0x4E];
} common_data_t;
extern common_data_t common_data;
+89
View File
@@ -8,7 +8,96 @@
extern "C" {
#endif
/**
* Event type definition
* xxxyyyyy yyyyyyyy yyyyyyyy yyyyyyyy
*
* x: event type (e.g. special event, 'first job' (chores) event, holidays, ...) (0-7)
* y: sub-type (specific event)
**/
#define mEv_SUBTYPE_BITS 29
#define mEv_TYPE_BITMASK (0b111 << mEv_SUBTYPE_BITS)
#define mEv_SUBTYPE_BITMASK ((1 << mEv_SUBTYPE_BITS) - 1)
#define mEv_GET_TYPE(event) (((event) & mEv_TYPE_BITMASK) >> mEv_SUBTYPE_BITS)
#define mEv_SET_TYPE(t) (((t) << mEv_SUBTYPE_BITS) & mEv_TYPE_BITMASK)
#define mEv_GET_SUBTYPE(event) ((event) & mEv_SUBTYPE_BITMASK)
#define mEv_SET_SUBTYPE(s) ((s) & mEv_SUBTYPE_BITMASK)
#define mEv_SET(type, subtype) (mEv_SET_TYPE(type) | mEv_SET_TYPE(subtype))
enum event_type {
mEv_SPNPC_EVENT, /* special NPC events */
mEv_SAVED_EVENT, /* events saved to data */
mEv_TYPE2_EVENT, /* unused? */
mEv_TYPE3_EVENT, /* unused? */
mEv_TYPE4_EVENT, /* unused? */
mEv_DAILY_EVENT, /* checked daily always? aSL_ReportShopOpen2Event has event 3 */
mEv_SPECL_EVENT, /* ??? secondary special npc event data? */
mEv_EVENT_NUM
};
enum events {
mEv_SPNPC_SHOP = (int)mEv_SET(mEv_SPNPC_EVENT, 0),
mEv_SPNPC_DESIGNER,
mEv_SPNPC_BROKER,
mEv_SPNPC_ARTIST,
mEv_SPNPC_ARABIAN,
mEv_SPNPC_GYPSY,
mEv_SAVED_RENEWSHOP = (int)mEv_SET(mEv_SAVED_EVENT, 0), /* renew shop */
mEv_SAVED_UNK1, /* unused */
/* intro through chores */
mEv_SAVED_FIRSTJOB_PLR0,
mEv_SAVED_FIRSTJOB_PLR1,
mEv_SAVED_FIRSTJOB_PLR2,
mEv_SAVED_FIRSTJOB_PLR3,
/* selecting house */
mEv_SAVED_FIRSTINTRO_PLR0,
mEv_SAVED_FIRSTINTRO_PLR1,
mEv_SAVED_FIRSTINTRO_PLR2,
mEv_SAVED_FIRSTINTRO_PLR3,
/* wait for next day to talk about HRA */
mEv_SAVED_HRAWAIT_PLR0,
mEv_SAVED_HRAWAIT_PLR1,
mEv_SAVED_HRAWAIT_PLR2,
mEv_SAVED_HRAWAIT_PLR3,
/* Nook will talk about HRA when entering the shop */
mEv_SAVED_HRATALK_PLR0,
mEv_SAVED_HRATALK_PLR1,
mEv_SAVED_HRATALK_PLR2,
mEv_SAVED_HRATALK_PLR3,
/* Do a 'favor' for a villager during chores */
mEv_SAVED_FJOPENQUEST_PLR0,
mEv_SAVED_FJOPENQUEST_PLR1,
mEv_SAVED_FJOPENQUEST_PLR2,
mEv_SAVED_FJOPENQUEST_PLR3,
/* Player going to another town, set at train station */
mEv_SAVED_GATEWAY_PLR0,
mEv_SAVED_GATEWAY_PLR1,
mEv_SAVED_GATEWAY_PLR2,
mEv_SAVED_GATEWAY_PLR3,
mEv_SAVED_GATEWAY_FRGN, /* Foreigner */
mEv_DAILY_0 = (int)mEv_SET(mEv_DAILY_EVENT, 0), /* unused */
mEv_DAILY_1, /* unused */
mEv_DAILY_2, /* unused */
mEv_DAILY_OPEN_SHOP, /* shop opened */
mEv_SPECL_DESIGNER_COMPLETE = (int)mEv_SET(mEv_SPECL_EVENT, 0)
};
extern int mEv_CheckFirstJob();
extern int mEv_CheckArbeit();
extern void mEv_debug_print4f(gfxprint_t* gfxprint);
extern void mEv_sp_debug_print4f(gfxprint_t* gfxprint);
+34
View File
@@ -9,6 +9,37 @@
extern "C" {
#endif
enum field_type {
mFI_FIELDTYPE_FG,
mFI_FIELDTYPE_1,
mFI_FIELDTYPE_2,
mFI_FIELDTYPE_ROOM,
mFI_FIELDTYPE_NPC_ROOM,
mFI_FIELDTYPE_DEMO,
mFI_FIELDTYPE_PLAYER_ROOM,
mFI_FIELDTYPE_NUM
};
#define mFI_TO_FIELD_ID(type, index) ((type << 12) | index)
#define mFI_GET_TYPE (field_id) (field_id & 0xF000)
enum field_room {
/* TODO: others */
mFI_FIELD_PLAYER0_ROOM = mFI_TO_FIELD_ID(mFI_FIELDTYPE_PLAYER_ROOM, 0),
mFI_FIELD_PLAYER1_ROOM,
mFI_FIELD_PLAYER2_ROOM,
mFI_FIELD_PLAYER3_ROOM,
/* TODO: others */
};
#define mFI_GET_PLAYER_ROOM_NO(field_id) (((field_id)-mFI_FIELD_PLAYER0_ROOM) & 3)
#define mFI_IS_PLAYER_ROOM(field_id) \
((field_id) == mFI_FIELD_PLAYER0_ROOM || (field_id) == mFI_FIELD_PLAYER1_ROOM || \
(field_id) == mFI_FIELD_PLAYER2_ROOM || (field_id) == mFI_FIELD_PLAYER3_ROOM)
/* Not sure about these other than the island one */
enum {
mFI_CLIMATE_0,
@@ -20,7 +51,10 @@ enum {
mFI_CLIMATE_NUM
};
extern mActor_name_t mFI_GetFieldId();
extern int mFI_GetClimate();
extern mActor_name_t* mFI_BkNumtoUtFGTop(int block_x, int block_z);
extern void mFI_ClearDeposit(int block_x, int block_z);
extern void mFI_PrintNowBGNum(gfxprint_t* gfxprint);
extern void mFI_PrintFgAttr(gfxprint_t* gfxprint);
+1
View File
@@ -85,6 +85,7 @@ typedef struct home_wall_floor_s {
typedef struct home_goki_s {
/* 0x00 */ lbRTC_time_c time; /* last time updated */
/* 0x08 */ u8 num; /* number of cockroaches in the house */
/* 0x09 */ u8 pad; /* unused outside of being initalized to 0 */
} mHm_goki_c;
/* sizeof(mHm_lyr_c) == 0x228 */
+23 -2
View File
@@ -37,8 +37,10 @@ enum {
#define ITEM_IS_FTR(n) \
(ITEM_NAME_GET_TYPE(n) == NAME_TYPE_FTR0 || ITEM_NAME_GET_TYPE(n) == NAME_TYPE_FTR1)
#define GET_NAME_ITEM0_CATEGORY(f) (((f)&0x800) >> 11)
#define GET_NAME_ITEM1_CATEGORY(f) (((f)&0xF00) >> 8)
#define ITEM_IS_ITEM1(n) (ITEM_NAME_GET_TYPE(n) == NAME_TYPE_ITEM1)
#define GET_NAME_ITEM0_CATEGORY(f) (((f) & 0x0800) >> 11)
#define GET_NAME_ITEM1_CATEGORY(f) (((f) & 0x0F00) >> 8)
#define EMPTY_NO 0x0000
@@ -47,6 +49,25 @@ enum {
#define FTR_TAPEDECK 0x1E58
#define ITM_TOOL_START 0x2200
#define ITM_NET ITM_TOOL_START
#define ITM_AXE 0x2201
#define ITM_SHOVEL 0x2202
#define ITM_ROD 0x2203
#define ITM_ENV_START 0x2900
#define ITM_SAPLING ITM_ENV_START
#define ITM_CEDAR_SAPLING 0x2901
#define ITM_WHITE_PANSY_BAG 0x2902
#define ITM_PURPLE_PANSY_BAG 0x2903
#define ITM_YELLOW_PANSY_BAG 0x2904
#define ITM_WHITE_COSMOS_BAG 0x2905
#define ITM_PINK_COSMOS_BAG 0x2906
#define ITM_BLUE_COSMOS_BAG 0x2907
#define ITM_RED_TULIP_BAG 0x2908
#define ITM_WHITE_TULIP_BAG 0x2909
#define ITEM_YELLOW_TULIP_BAG 0x290A
#define ITM_COLLEGERULE 0x2B00
#define FTR_ORANGEBOX 0x30F8
+20 -1
View File
@@ -3,18 +3,37 @@
#include "types.h"
#include "m_actor_type.h"
#include "game.h"
#ifdef __cplusplus
extern "C" {
#endif
#define mPB_POLICE_BOX_ITEM_STORAGE_COUNT 20
#define mPB_POLICE_BOX_ITEM_STORAGE_COUNT 20 /* total storage space */
#define mPB_MAX_GROW_SIZE 5 /* Maximum number of items to trigger generating random new items */
/* Possible new items to add to lost and found */
enum police_box_category {
mPB_CATEGORY_GOODS,
mPB_CATEGORY_ITEM,
mPB_CATEGORY_FLOWER,
mPB_CATEGORY_UMBRELLA,
mPB_CATEGORY_NUM
};
/* sizeof(PoliceBox_c) == 0x28 */
typedef struct police_box_s {
/* 0x00 */ mActor_name_t keep_items[mPB_POLICE_BOX_ITEM_STORAGE_COUNT];
} PoliceBox_c;
extern void mPB_copy_itemBuf(mActor_name_t* item_buf);
extern int mPB_get_keep_item_sum();
extern void mPB_keep_item(mActor_name_t item_no);
extern void mPB_keep_all_item_in_block(int blk_x, int blk_z);
extern void mPB_force_set_keep_item();
extern void mPB_police_box_init(GAME* game);
#ifdef __cplusplus
}
#endif
+25
View File
@@ -0,0 +1,25 @@
#ifndef M_SCENE_TABLE_H
#define M_SCENE_TABLE_H
#include "types.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
TODO: is this right? I assume so based on file names but
there may be a better place for this
*/
enum scene_table {
/* TODO: finish */
SCENE_ISLAND_COTTAGE = 0x2F,
/* TODO: finish */
};
#ifdef __cplusplus
}
#endif
#endif
+77 -7
View File
@@ -6,6 +6,7 @@
#include "lb_rtc.h"
#include "m_personal_id.h"
#include "m_actor_type.h"
#include "game.h"
#ifdef __cplusplus
extern "C" {
@@ -15,14 +16,81 @@ extern "C" {
#define mSP_GOODS_COUNT 39
#define mSP_LOTTERY_ITEM_COUNT 3
/* item list groups */
enum {
mSP_LIST_FURNITURE,
mSP_LIST_PAPER,
mSP_LIST_CLOTH,
mSP_LIST_CARPET,
mSP_LIST_WALLPAPER,
mSP_LIST_A, /* A priority list */
mSP_LIST_B, /* B priority list */
mSP_LIST_C, /* C priority list */
mSP_LIST_EVENT, /* event list */
mSP_LIST_TRAIN, /* */
mSP_LIST_LOTTERY, /* lottery list */
mSP_LIST_HALLOWEEN, /* halloween theme list */
mSP_LIST_PRESENT, /* */
mSP_LIST_CHRISTMAS,
mSP_LIST_SNOW,
mSP_LIST_HALLOWEEN2,
mSP_LIST_JONASON,
mSP_LIST_POSTOFFICE,
mSP_LIST_NINTENDO64,
mSP_LIST_SPECIALPRESENT,
mSP_LIST_ISLAND,
mSP_LIST_HOMEPAGE,
mSP_LIST_EVENTPRESENTCHUMON,
mSP_LIST_KAMAKURA,
mSP_LIST_ISLANDFAMICOM,
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_MAX
mSP_LIST_NUM
};
/* item List types */
enum {
mSP_LISTTYPE_COMMON, /* common ABC priority list */
mSP_LISTTYPE_UNCOMMON, /* uncommon ABC priority list */
mSP_LISTTYPE_RARE, /* rare ABC priority list */
mSP_LISTTYPE_EVENT, /* event list */
mSP_LISTTYPE_TRAIN, /* */
mSP_LISTTYPE_LOTTERY, /* lottery list */
mSP_LISTTYPE_HALLOWEEN, /* halloween theme list */
mSP_LISTTYPE_PRESENT, /* */
mSP_LISTTYPE_ABC, /* ABC */
mSP_LISTTYPE_CHRISTMAS,
mSP_LISTTYPE_SNOW,
mSP_LISTTYPE_HALLOWEEN2,
mSP_LISTTYPE_JONASON,
mSP_LISTTYPE_POSTOFFICE,
mSP_LISTTYPE_NINTENDO64,
mSP_LISTTYPE_SPECIALPRESENT,
mSP_LISTTYPE_ISLAND,
mSP_LISTTYPE_HOMEPAGE,
mSP_LISTTYPE_EVENTPRESENTCHUMON,
mSP_LISTTYPE_KAMAKURA,
mSP_LISTTYPE_ISLANDFAMICOM,
mSP_LISTTYPE_HARVEST,
mSP_LISTTYPE_MARIO,
mSP_LISTTYPE_TENT,
mSP_LISTTYPE_NUM
};
/* item list kinds */
enum {
mSP_KIND_FURNITURE,
mSP_KIND_PAPER,
mSP_KIND_CLOTH,
mSP_KIND_CARPET,
mSP_KIND_WALLPAPER,
mSP_KIND_MAX
};
/* sizeof(mSP_goods_priority_list_c) == 1 */
@@ -35,7 +103,7 @@ typedef struct shop_goods_priority_list_s {
/* sizeof(Shop_c) == 0x140 */
typedef struct shop_s {
/* 0x000 */ mSP_goods_priority_list_c priority_lists[mSP_LIST_MAX]; /* ABC list rarity (known internally as priority) */
/* 0x000 */ mSP_goods_priority_list_c priority_lists[mSP_KIND_MAX]; /* ABC list rarity (known internally as priority) */
/* 0x006 */ PersonalID_c unused_ids[mSP_PERSONAL_ID_COUNT]; /* unused personal ids */
/* 0x0CE */ mActor_name_t items[mSP_GOODS_COUNT]; /* standard shop items */
/* 0x11C */ mActor_name_t rare_item; /* spotlight rare item taken from rare furniture ABC list */
@@ -56,6 +124,8 @@ typedef struct shop_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 void mItemDebug_ItemDebugMain();
extern void mItemDebug_ItemDebugDraw(gfxprint_t* gfxprint);
+310
View File
@@ -0,0 +1,310 @@
#include "m_cockroach.h"
#include "m_home.h"
#include "m_house.h"
#include "m_private.h"
#include "m_field_info.h"
#include "m_scene_table.h"
#include "m_common_data.h"
/**
* @brief Clamps the input cockroach count between [0, mCkRh_MAX_NUM].
*
* @param count The new cockroach count
* @return The clamped cockroach count
**/
static int mCkRh_GokiFamilyCount2Good(int count) {
if (count < 0) {
return 0;
}
return (count <= mCkRh_MAX_NUM ? count : mCkRh_MAX_NUM);
}
/**
* @brief Initializes all house cockroach save data for unclaimed houses
* when a new Player is created.
**/
extern void mCkRh_InitGokiSaveData_InitNewPlayer() {
int i;
for (i = 0; i < PLAYER_NUM; i++) {
if (mHS_get_pl_no_detail(i) == -1) {
mCkRh_InitGokiSaveData_1Room(i);
}
}
}
/**
* @brief Initializes a single house's cockroach data by house index.
*
* @param home_no The house index whose cockroach data will be initialized
**/
extern void mCkRh_InitGokiSaveData_1Room(int home_no) {
mCkRh_InitGokiSaveData_1Room_ByHomeData(Save_GetPointer(homes[home_no]));
}
/**
* @brief Initializes a single house's cockroach data.
*
* @param home The mHm_hs_c house whose cockroach data wil be initialized.
**/
extern void mCkRh_InitGokiSaveData_1Room_ByHomeData(mHm_hs_c* home) {
home->goki.num = 0;
home->goki.pad = 0;
home->goki.time = Common_Get(time.rtc_time);
}
/**
* @brief Initializes island cottage cockroach data.
**/
extern void mCkRh_InitGokiSaveData_IslandPlayerRoom() {
const lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
Save_Set(island.cottage.goki.num, 0);
Save_Set(island.cottage.goki.pad, 0);
Save_Set(island.cottage.goki.time.year, rtc_time->year);
Save_Set(island.cottage.goki.time.month, rtc_time->month);
Save_Set(island.cottage.goki.time.day, rtc_time->day);
}
/**
* @brief Initializes all houses' cockroach data even if a player owns it.
**/
extern void mCkRh_InitGokiSaveData_AllRoom() {
int i;
for (i = 0; i < PLAYER_NUM; i++) {
mCkRh_InitGokiSaveData_1Room(i);
}
}
/**
* @brief Updates the cockroach 'last entered' time for the island cottage.
*
* @param scene_id The current scene id
**/
extern void mCkRh_SetGoingOutCottageTime(int scene_id) {
if (scene_id == SCENE_ISLAND_COTTAGE) {
Save_Set(island.cottage.goki.time.year, Common_Get(time.rtc_time.year));
Save_Set(island.cottage.goki.time.month, Common_Get(time.rtc_time.month));
Save_Set(island.cottage.goki.time.day, Common_Get(time.rtc_time.day));
}
}
/**
* @brief Updates the cockroach 'last entered' time for a player's house.
*
* @param player_no The index of the player whose cockroach data will be updated
**/
extern void mCkRh_SavePlayTime(int player_no) {
if (player_no < PLAYER_NUM) {
int home_no = mHS_get_arrange_idx(player_no);
Save_Set(homes[home_no & 3].goki.time, Common_Get(time.rtc_time));
}
}
/**
* @brief Returns the inverval in days between the current time and
* the last time that the player's cockroach 'last enter time'.
*
* @param player_no The index of the player whose 'days gap' will be calculated
* @return When a foriegner, 0, otherwise day interval
**/
static int mCkRh_DaysGapCompareWithSaveTime(int player_no) {
int homeid;
lbRTC_time_c goki_time;
int interval;
if (player_no < PLAYER_NUM) {
homeid = mHS_get_arrange_idx(player_no) & 3;
goki_time.year = Save_Get(homes[homeid].goki.time.year);
goki_time.month = Save_Get(homes[homeid].goki.time.month);
goki_time.day = Save_Get(homes[homeid].goki.time.day);
goki_time.weekday = lbRTC_Week(goki_time.year, goki_time.month, goki_time.day);
goki_time.hour = 1;
goki_time.min = 1;
goki_time.sec = 1;
interval = lbRTC_GetIntervalDays(&goki_time, Common_GetPointer(time.rtc_time));
}
else {
interval = 0;
}
return interval;
}
/**
* @brief Gets the day interval between current time and the island cottage
* cockroach last enter time.
*
* @return days between current time and last island cottage enter time
**/
static int mCkRh_DaysGapCompareWithCottageSaveTime() {
lbRTC_time_c goki_time;
goki_time.year = Save_Get(island.cottage.goki.time.year);
goki_time.month = Save_Get(island.cottage.goki.time.month);
goki_time.day = Save_Get(island.cottage.goki.time.day);
goki_time.weekday = lbRTC_Week(goki_time.year, goki_time.month, goki_time.day);
goki_time.hour = 1;
goki_time.min = 1;
goki_time.sec = 1;
return lbRTC_GetIntervalDays(&goki_time, Common_GetPointer(time.rtc_time));
}
/**
* @brief Determines and updates the saved cockroach number for a player.
*
* The minimum day interval between the current time and the cockroach's
* 'last entered time' is 7 days. The amount you get scales linearly,
* starting with 1 new cockroach on day 7, 2 new on day 8, ...
*
* The maximum number of cockroaches is clamped to mCkRh_MAX_NUM which stock
* is 10 cockroaches.
*
* @param player_no The inex of the player whose cockroach data will be updated
**/
extern void mCkRh_DecideNowGokiFamilyCount(int player_no) {
int count;
int day_gap;
int home_no;
int goki_num;
/* player must live in town */
if (player_no < PLAYER_NUM) {
day_gap = mCkRh_DaysGapCompareWithSaveTime(player_no);
home_no = mHS_get_arrange_idx(player_no) & 3;
if (day_gap > mCkRh_INTERVAL_DAYS) {
goki_num = Save_Get(homes[home_no].goki.num);
count = goki_num > 0 ? day_gap : day_gap - mCkRh_INTERVAL_DAYS;
Save_Set(homes[home_no].goki.num, mCkRh_GokiFamilyCount2Good(count + goki_num));
}
}
day_gap = mCkRh_DaysGapCompareWithCottageSaveTime();
if (day_gap > mCkRh_INTERVAL_DAYS) {
u8* goki_num = Save_GetPointer(island.cottage.goki.num);
count = (int)*goki_num > 0 ? day_gap : day_gap - mCkRh_INTERVAL_DAYS;
*goki_num = mCkRh_GokiFamilyCount2Good(count + (int)*goki_num);
}
}
/**
* @brief Adds a specific amount of cockroaches to the current player's house.
*
* @param count The number of cockroaches to add (total clamped to mCkRh_MAX_NUM)
* @return TRUE/FALSE cockroach data was updated
**/
extern int mCkRh_PlussGokiN_NowRoom(int count, int scene_no) {
mActor_name_t fieldid = mFI_GetFieldId();
if (mFI_IS_PLAYER_ROOM(fieldid)) {
int player_no = Common_Get(player_no);
int house_field_id = mFI_GET_PLAYER_ROOM_NO(fieldid);
int home_id = mHS_get_arrange_idx(player_no) & 3;
if ((player_no < PLAYER_NUM) && (house_field_id == home_id)) {
Save_Set(homes[home_id].goki.num, mCkRh_GokiFamilyCount2Good(count + Save_Get(homes[home_id].goki.num)));
return TRUE;
}
}
else if (scene_no == SCENE_ISLAND_COTTAGE) {
u8* goki_num = Save_GetPointer(island.cottage.goki.num);
*goki_num = mCkRh_GokiFamilyCount2Good(count + *goki_num);
}
return FALSE;
}
/**
* @brief Removes a specific amount of cockroaches to the current player's house.
*
* @param count The number of cockroaches to remove (minimum clamped to 0)
* @return TRUE/FALSE cockroach data was updated
**/
extern int mCkRh_MinusGokiN_NowRoom(int count, int scene_id) {
mActor_name_t field_id = mFI_GetFieldId();
if (mFI_IS_PLAYER_ROOM(field_id)) {
int player_no = Common_Get(player_no);
int house_field_id = mFI_GET_PLAYER_ROOM_NO(field_id);
int home_no = mHS_get_arrange_idx(player_no) & 3;
if (player_no < PLAYER_NUM && house_field_id == home_no) {
Save_Set(homes[home_no].goki.num, mCkRh_GokiFamilyCount2Good(Save_Get(homes[home_no].goki.num) - count));
return TRUE;
}
}
else if (scene_id == SCENE_ISLAND_COTTAGE) {
u8* goki_num = Save_GetPointer(island.cottage.goki.num);
*goki_num = mCkRh_GokiFamilyCount2Good(*goki_num - count);
}
return FALSE;
}
/**
* @brief Gets the cockroach count for the current scene id.
*
* @return
* - in player house: house cockroach count
* - in island octtage: island cottage cockroach count
* - elsewhere: 0
**/
extern int mCkRh_NowSceneGokiFamilyCount() {
mActor_name_t fieldid = mFI_GetFieldId();
if (mFI_IS_PLAYER_ROOM(fieldid)) {
return Save_Get(homes[mFI_GET_PLAYER_ROOM_NO(fieldid)].goki.num);
}
else if (Save_Get(scene_no) == SCENE_ISLAND_COTTAGE) {
return Save_Get(island.cottage.goki.num);
}
return 0;
}
/**
* @brief Initializes the 'can_look_goki_count' variable to 0.
*
* This variable controls how many cockroaches are currently
* visible to the player in a room.
**/
extern void mCkRh_InitCanLookGokiCount() {
Common_Set(can_look_goki_count, 0);
}
/**
* @brief Changes the 'can_look_goki_count' variable by 'count'.
*
* 'can_look_goki_count' is clamped between
*
* @param count The number of visible cockroaches to add/remove
* @return TRUE/FALSE were number of visible cockroaches updated?
**/
extern int mCkRh_CalcCanLookGokiCount(int count) {
count += Common_Get(can_look_goki_count);
if (count < 0) {
Common_Set(can_look_goki_count, 0);
return FALSE;
}
if (count > mCkRh_CAN_LOOK_GOKI_NUM) {
Common_Set(can_look_goki_count, mCkRh_CAN_LOOK_GOKI_NUM);
return FALSE;
}
Common_Set(can_look_goki_count, count);
return TRUE;
}
/**
* @brief Retrieves the 'can_look_gooki_count' value.
*
* @return number of cockroaches currently visible to the player
**/
extern int mCkRh_GetCanLookGokiCount() {
return Common_Get(can_look_goki_count);
}
+311
View File
@@ -0,0 +1,311 @@
#include "m_police_box.h"
#include "game.h"
#include "m_actor_type.h"
#include "libc64/qrand.h"
#include "m_common_data.h"
#include "m_name_table.h"
#include "m_field_info.h"
#include "m_field_make.h"
#include "libultra/libultra.h"
#include "m_lib.h"
#include "m_shop.h"
/**
* @brief Copies an array of items to the lost and found.
*
* item_buf must have a length of at least mPB_POLICE_BOX_ITEM_STORAGE_COUNT.
*
* @param item_buf The array of items to copy
**/
extern void mPB_copy_itemBuf(mActor_name_t* item_buf) {
mActor_name_t* keep_item;
int count;
int i;
keep_item = Save_Get(police_box.keep_items);
count = 0;
/* copy over the items */
for (i = 0; i < mPB_POLICE_BOX_ITEM_STORAGE_COUNT; i++) {
if (*item_buf != EMPTY_NO) {
*keep_item = *item_buf;
count++;
keep_item++;
}
item_buf++;
}
/* clear out any unset items if necessary */
for (i = count; i < mPB_POLICE_BOX_ITEM_STORAGE_COUNT; i++) {
*keep_item++ = EMPTY_NO;
}
}
/**
* @brief Gets the number of used slots in the lost and found.
*
* @return count of used slots
**/
extern int mPB_get_keep_item_sum() {
int i;
mActor_name_t* keep_item = Save_Get(police_box.keep_items);
int sum = 0;
for (i = 0; i < mPB_POLICE_BOX_ITEM_STORAGE_COUNT; i++) {
if (*keep_item != EMPTY_NO) {
sum++;
}
keep_item++;
}
return sum;
}
/**
* @brief Adds an item to the lost and found.
*
* The item must be of type 'ITEM1' or 'FTR0/FTR1'.
* If the lost and found is full, the first item in it
* will be deleted and all subsequent items will be shifted
* over by one.
*
* @param item_no The item to add
**/
extern void mPB_keep_item(mActor_name_t item_no) {
if (ITEM_IS_ITEM1(item_no) || ITEM_IS_FTR(item_no)) {
int keep_item_sum = mPB_get_keep_item_sum();
if (keep_item_sum >= mPB_POLICE_BOX_ITEM_STORAGE_COUNT) {
/* delete the first item and move the rest down one slot */
mActor_name_t* keep_item = Save_Get(police_box.keep_items);
int i;
for (i = 0; i < mPB_POLICE_BOX_ITEM_STORAGE_COUNT - 1; i++) {
keep_item[0] = keep_item[1];
keep_item++;
}
keep_item_sum = mPB_POLICE_BOX_ITEM_STORAGE_COUNT - 1;
}
Save_Set(police_box.keep_items[keep_item_sum], item_no);
}
}
/**
* @brief Transfers all items of type 'ITEM1' and 'FTR0/FTR1' to the lost and found.
*
* If the number of items to add exceeds the size of the lost and found,
* the items kept will be randomly selected by using rng to overwrite
* previously saved items from the acre.
*
* Additionally, items already in the lost in found will be deleted to
* make space for the new items if necessary.
*
* @param blk_x The x acre (column)
* @param blk_z The z acre (row)
**/
extern void mPB_keep_all_item_in_block(int blk_x, int blk_z) {
int count;
mActor_name_t new_items[mPB_POLICE_BOX_ITEM_STORAGE_COUNT];
int keep_item_sum;
mActor_name_t item;
mActor_name_t* block_items;
int i;
keep_item_sum = mPB_get_keep_item_sum();
block_items = mFI_BkNumtoUtFGTop(blk_x, blk_z);
count = 0;
bzero(new_items, mPB_POLICE_BOX_ITEM_STORAGE_COUNT * sizeof(mActor_name_t));
for (i = 0; i < UT_X_NUM * UT_Z_NUM; i++) {
int item_type;
item = *block_items;
/* only accept items in the 0x1XXX, 2XXX, and 3XXX range */
item_type = ITEM_NAME_GET_TYPE(item);
if (item_type == NAME_TYPE_FTR0 || item_type == NAME_TYPE_ITEM1 || item_type == NAME_TYPE_FTR1) {
if (count < mPB_POLICE_BOX_ITEM_STORAGE_COUNT) {
/* space is still available, so directly add it */
new_items[count++] = item;
}
else {
/* randomly overwrite one of the items in the lost and found */
new_items[(int)(fqrand() * mPB_POLICE_BOX_ITEM_STORAGE_COUNT)] = item;
}
*block_items = EMPTY_NO;
}
block_items++;
}
if (count > 0) {
int total_sum = count + keep_item_sum;
if (total_sum <= mPB_POLICE_BOX_ITEM_STORAGE_COUNT) {
mem_copy((u8*)(Save_Get(police_box.keep_items) + keep_item_sum), (u8*)new_items, count * sizeof(mActor_name_t));
}
else {
mActor_name_t* dst = Save_Get(police_box.keep_items);
int save_count = total_sum - mPB_POLICE_BOX_ITEM_STORAGE_COUNT;
int keep_sum = keep_item_sum - save_count;
/* move over saved items already in lost and found */
for (i = 0; i < keep_sum; i++) {
dst[i] = dst[i + save_count];
}
/* copy newly added items */
mem_copy((u8*)(Save_Get(police_box.keep_items) + keep_sum), (u8*)new_items, count * sizeof(mActor_name_t));
}
}
/* clear buried item flags in the cleared acre */
mFI_ClearDeposit(blk_x, blk_z);
}
/* select random item function definition */
typedef mActor_name_t (*mPB_get_force_set_proc)();
/**
* @brief Selects a random 'goods' item to add to the lost and found/
*
* @return The randomly selected item
**/
static mActor_name_t mPB_get_force_set_item_goods() {
static int category_table[mSP_KIND_MAX] = {
mSP_KIND_FURNITURE,
mSP_KIND_PAPER,
mSP_KIND_CLOTH,
mSP_KIND_CARPET,
mSP_KIND_WALLPAPER
};
static int prob_table[mSP_KIND_MAX] = {
35, /* furniture 0-35 (36%) */
58, /* stationery 36-58 (23%) */
88, /* clothing 59-88 (30%) */
94, /* carpets 89-94 (6%) */
100 /* wallpaper 95-99 (5%) (fqrand is [min, max) so 100 is not possible) */
};
int category = mSP_KIND_MAX;
mActor_name_t item = EMPTY_NO;
int roll = (int)(fqrand() * 100.0f);
int i;
for (i = 0; i < mSP_KIND_MAX; i++) {
if (roll <= prob_table[i]) {
category = i;
break;
}
}
mSP_SelectRandomItem_New(NULL, &item, 1, NULL, 0, category_table[category], mSP_LISTTYPE_COMMON, FALSE);
return item;
}
/**
* @brief Selects a random tool or sapling to add to the lost and found.
*
* @return The randomly selected item
**/
static mActor_name_t mPB_get_force_set_item_item() {
static mActor_name_t category_table[6] = {
ITM_NET, ITM_AXE, ITM_SHOVEL, ITM_ROD, ITM_SAPLING, ITM_CEDAR_SAPLING
};
return category_table[(int)(fqrand() * 6.0f)];
}
/**
* @brief Selects a random flower bag to add to the lost and found.
*
* @return The randomly selected flower bag
**/
static mActor_name_t mPB_get_force_set_item_flower() {
return ITM_WHITE_PANSY_BAG + (int)(fqrand() * 8.0f);
}
/**
* @brief Selects a random umbrella to add to the lost and found.
*
* @return The randomly selected umbrella
**/
static mActor_name_t mPB_get_force_set_item_umbrella() {
mActor_name_t umbrella;
mSP_RandomUmbSelect(&umbrella, 1);
return umbrella;
}
/**
* @brief Selects a random item from a random category to add to the lost and found.
*
* @return The randomly selected item
**/
static mActor_name_t mPB_get_force_set_item() {
static mPB_get_force_set_proc force_proc[mPB_CATEGORY_NUM] = {
&mPB_get_force_set_item_goods,
&mPB_get_force_set_item_item,
&mPB_get_force_set_item_flower,
&mPB_get_force_set_item_umbrella
};
static int prob_table[mPB_CATEGORY_NUM] = {
85, /* 0-85 (86%) 'goods' */
90, /* 86-90 (5%) 'item' */
95, /* 91-95 (5%) 'flower' */
100 /* 96-100 (4%) 'umbrella' (again, fqrand is [min, max) therefore 100 is never possible) */
};
int proc = mPB_CATEGORY_NUM;
int roll = (int)(fqrand() * 100.0f);
int i;
for (i = 0; i < mPB_CATEGORY_NUM; i++) {
if (roll <= prob_table[i]) {
proc = i;
break;
}
}
return (*force_proc[proc])();
}
/**
* @brief Adds a random item to the lost and found if grow space is available.
**/
extern void mPB_force_set_keep_item() {
/* if lost and found item count is less-than-equal-to max grow size & 50-50 roll */
if (mPB_get_keep_item_sum() <= mPB_MAX_GROW_SIZE && (int)qrand() >= 0) {
mPB_keep_item(mPB_get_force_set_item());
}
}
/**
* @brief Initializes the police station lost and found.
*
* The lost and found will always start with one random common
* priority list furniture and two random common priority list
* shirts.
*
* @param game The GAME pointer to pass to mSP_SelectRandomItem_New, goes unused
**/
extern void mPB_police_box_init(GAME* game) {
mActor_name_t* keep_items = Save_Get(police_box.keep_items);
int i;
/* generate one random ABC prio furniture and two random ABC prio shirts */
mSP_SelectRandomItem_New(game, keep_items + 0, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_ABC, FALSE);
mSP_SelectRandomItem_New(game, keep_items + 1, 2, NULL, 0, mSP_KIND_CLOTH, mSP_LISTTYPE_ABC, FALSE);
/* clear the rest of the lost and found */
keep_items += 3;
for (i = 0; i < mPB_POLICE_BOX_ITEM_STORAGE_COUNT - 3; i++) {
*keep_items++ = EMPTY_NO;
}
}