From d583190d683c2098cc53b92477d553da2fb178f0 Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Sat, 27 May 2023 00:50:20 -0400 Subject: [PATCH] Implement & link ac_set_ovl_insect.c --- config/rel_slices.yml | 5 + include/ac_insect_h.h | 59 + include/ac_set_manager.h | 21 +- include/ac_set_ovl_insect.h | 126 +++ include/m_clip.h | 5 +- include/m_collision_bg.h | 24 +- include/m_common_data.h | 6 +- include/m_event.h | 15 + include/m_field_info.h | 3 + include/m_kankyo.h | 12 +- include/m_name_table.h | 12 + rel/ac_set_manager.c | 2 +- rel/ac_set_ovl_gyoei.c | 2 +- rel/ac_set_ovl_insect.c | 2138 +++++++++++++++++++++++++++++++++++ 14 files changed, 2416 insertions(+), 14 deletions(-) create mode 100644 include/ac_insect_h.h create mode 100644 rel/ac_set_ovl_insect.c diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 4909e07d..e747e333 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -111,6 +111,11 @@ ac_set_ovl_gyoei.c: .rodata: [0x80644DD0, 0x80644E00] .data: [0x8068BCF0, 0x8068CDE8] .bss: [0x812FCD00, 0x812FD048] +ac_set_ovl_insect.c: + .text: [0x8049A9E4, 0x8049C748] + .rodata: [0x80644E00, 0x80644E28] + .data: [0x8068CDE8, 0x8068E3C0] + .bss: [0x812FD048, 0x812FD270] m_huusui_room_ovl.c: .text: [0x804D1BBC, 0x804D2164] .rodata: [0x80646558, 0x806465C8] diff --git a/include/ac_insect_h.h b/include/ac_insect_h.h new file mode 100644 index 00000000..402888aa --- /dev/null +++ b/include/ac_insect_h.h @@ -0,0 +1,59 @@ +#ifndef AC_INSECT_H_H +#define AC_INSECT_H_H + +#include "types.h" +#include "m_actor.h" +#include "m_lib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* sizeof(aINS_Init_c) == 0x18 */ +typedef struct insect_init_s { + /* 0x00 */ int insect_type; + /* 0x04 */ xyz_t position; + /* 0x10 */ int extra_data; + /* 0x14 */ GAME* game; +} aINS_Init_c; + +/* sizeof(aINS_INSECT_DUMMY_ACTOR) == 0x288 */ +typedef struct insect_dummy_actor_s { + ACTOR actor; + /* TODO: finish */ +} aINS_INSECT_DUMMY_ACTOR; + +typedef aINS_INSECT_DUMMY_ACTOR* (*aINS_make_insect_proc)(aINS_Init_c*, int); +typedef void (*aINS_make_ant_proc)(aINS_Init_c*, s8, s8); +typedef void (*aINS_dt_proc)(ACTOR*, GAME*); +typedef aINS_INSECT_DUMMY_ACTOR* (*aINS_make_actor_proc)(GAME*, int, xyz_t*); +typedef void (*aINS_set_pl_act_tim_proc)(int, int, int); +typedef int (*aINS_chk_live_insect_proc)(int, int, GAME*); +typedef void (*aINS_position_move_proc)(ACTOR*); +typedef ACTOR* (*aINS_search_near_insect_proc)(GAME*, f32, f32); + +/* sizeof(aINS_Clip_c) == 0x50 */ +typedef struct ac_insect_clip_s { + /* 0x00 */ aINS_make_insect_proc make_insect_proc; + /* 0x04 */ aINS_make_ant_proc make_ant_proc; // unused clip proc in AC + /* 0x08 */ void* unused_08; + /* 0x0C */ aINS_dt_proc dt_proc; + /* 0x10 */ aINS_make_actor_proc make_actor_proc; + /* 0x14 */ aINS_set_pl_act_tim_proc set_pl_act_tim_proc; + /* 0x18 */ aINS_chk_live_insect_proc chk_live_insect_proc; + /* 0x1C */ aINS_search_near_insect_proc search_near_insect_proc; + /* 0x20 */ int pl_action; + /* 0x24 */ int pl_action_ut_x; + /* 0x28 */ int pl_action_ut_z; + /* 0x2C */ aINS_position_move_proc position_move_proc; + /* 0x30 */ int ant_spawn_pending; + /* 0x34 */ aINS_Init_c ant_spawn_info; + /* 0x4C */ u8 ant_ut_x; + /* 0x4D */ u8 ant_ut_z; +} aINS_Clip_c; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/ac_set_manager.h b/include/ac_set_manager.h index 194a5a12..e9e1e8c0 100644 --- a/include/ac_set_manager.h +++ b/include/ac_set_manager.h @@ -12,7 +12,24 @@ extern "C" { typedef struct actor_set_manager_s SET_MANAGER; #define aSetMgr_SET_OVERLAY_BUF_SIZE 0x4000 -#define aSetMgr_KEEP_SIZE 0x354 + +#define aSetMgr_INSECT_SPAWN_INFO_COUNT 43 + +/* sizeof(aSOI_insect_spawn_info_f_c) == 0xC */ +typedef struct insect_spawn_info_f_s { + int type; + u8 spawn_area; + float weight; +} aSOI_insect_spawn_info_f_c; + +/* sizeof(aSOI_insect_keep_c) == 0x210 */ +typedef struct insect_keep_s { + aSOI_insect_spawn_info_f_c spawn_info[aSetMgr_INSECT_SPAWN_INFO_COUNT]; // devs forgot to update aSetMgr_INSECT_SPAWN_INFO_SIZE or something lol + int now_month; + int now_term; + u8 info_num; + u8 spawn_type; +} aSOI_insect_keep_c; #define aSetMgr_WAIT_TIME 5 // wait time between aSetMgr_move_check_wait -> aSetMgr_move_set @@ -51,7 +68,7 @@ enum set_manager_move_proc_type { /* sizeof(aSetMgr_keep_c) == 0x354 */ typedef struct actor_set_manager_keep_s { - /* 0x000 */ u8 unk[0x210]; + /* 0x000 */ aSOI_insect_keep_c insect_keep; /* 0x210 */ aSOG_gyoei_keep_c gyoei_keep; } aSetMgr_keep_c; diff --git a/include/ac_set_ovl_insect.h b/include/ac_set_ovl_insect.h index 686f8514..64ff4838 100644 --- a/include/ac_set_ovl_insect.h +++ b/include/ac_set_ovl_insect.h @@ -2,11 +2,137 @@ #define AC_SET_OVL_INSECT_H #include "types.h" +#include "ac_set_manager.h" #ifdef __cplusplus extern "C" { #endif +#define aSOI_TERM_TRANSITION_MAX_DAYS 5 + +#define aSOI_INSECT_TYPE_INVALID -1 + +enum insect_type { + aSOI_INSECT_TYPE_COMMON_BUTTERFLY, + aSOI_INSECT_TYPE_YELLOW_BUTTERFLY, + aSOI_INSECT_TYPE_TIGER_BUTTERFLY, + aSOI_INSECT_TYPE_PURPLE_BUTTERFLY, + aSOI_INSECT_TYPE_ROBUST_CICADA, + aSOI_INSECT_TYPE_WALKER_CICADA, + aSOI_INSECT_TYPE_EVENING_CICADA, + aSOI_INSECT_TYPE_BROWN_CICADA, + aSOI_INSECT_TYPE_BEE, + aSOI_INSECT_TYPE_COMMON_DRAGONFLY, + aSOI_INSECT_TYPE_RED_DRAGONFLY, + aSOI_INSECT_TYPE_DARNER_DRAGONFLY, + aSOI_INSECT_TYPE_BANDED_DRAGONFLY, + aSOI_INSECT_TYPE_LONG_LOCUST, + aSOI_INSECT_TYPE_MIGRATORY_LOCUST, + aSOI_INSECT_TYPE_CRICKET, + aSOI_INSECT_TYPE_GRASSHOPPER, + aSOI_INSECT_TYPE_BELL_CRICKET, + aSOI_INSECT_TYPE_PINE_CRICKET, + aSOI_INSECT_TYPE_DRONE_BEETLE, + aSOI_INSECT_TYPE_DYNASTID_BEETLE, + aSOI_INSECT_TYPE_FLAT_STAG_BEETLE, + aSOI_INSECT_TYPE_JEWEL_BEETLE, + aSOI_INSECT_TYPE_LONGHORN_BEETLE, + aSOI_INSECT_TYPE_LADYBUG, + aSOI_INSECT_TYPE_SPOTTED_LADYBUG, + aSOI_INSECT_TYPE_MANTIS, + aSOI_INSECT_TYPE_FIREFLY, + aSOI_INSECT_TYPE_COCKROACH, + aSOI_INSECT_TYPE_SAW_STAG_BEETLE, + aSOI_INSECT_TYPE_MOUNTAIN_BEETLE, + aSOI_INSECT_TYPE_GIANT_BEETLE, + aSOI_INSECT_TYPE_SNAIL, + aSOI_INSECT_TYPE_MOLE_CRICKET, + aSOI_INSECT_TYPE_POND_SKATER, + aSOI_INSECT_TYPE_BAGWORM, + aSOI_INSECT_TYPE_PILL_BUG, + aSOI_INSECT_TYPE_SPIDER, + aSOI_INSECT_TYPE_ANT, + aSOI_INSECT_TYPE_MOSQUITO, + aSOI_INSECT_TYPE_NUM, + + aSOI_INSECT_TYPE_SPIRIT = aSOI_INSECT_TYPE_NUM, + aSOI_INSECT_TYPE_NONE, + aSOI_INSECT_TYPE_EXTENDED_NUM +}; + +#define aSOI_SPAWN_AREA_INVALID -1 + +enum insect_spawn_area { + aSOI_SPAWN_AREA_ON_TREE, + aSOI_SPAWN_AREA_ON_FLOWER, + aSOI_SPAWN_AREA_RAINING_ON_FLOWER, + aSOI_SPAWN_AREA_FLYING, + aSOI_SPAWN_AREA_ON_GROUND, + aSOI_SPAWN_AREA_IN_BUSH, + aSOI_SPAWN_AREA_FLYING_NEAR_WATER, + aSOI_SPAWN_AREA_ON_WATER, + aSOI_SPAWN_AREA_ON_CANDY, + aSOI_SPAWN_AREA_ON_TRASH, + aSOI_SPAWN_AREA_UNDER_ROCK, + aSOI_SPAWN_AREA_UNDERGROUND, + aSOI_SPAWN_AREA_FLYING_NEAR_FLOWERS_OR_AROUND, /* this prefers flowers, but will default to "FLYING" if no flowers are in the acre */ + aSOI_SPAWN_AREA_NOTHING, + + aSOI_SPAWN_AREA_NUM +}; + +enum insect_spawn_type { + aSOI_SPAWN_TYPE_NONE, /* none/unused? */ + aSOI_SPAWN_TYPE_TOWN, /* pull from town spawns */ + aSOI_SPAWN_TYPE_ISLAND, /* pull from island spawns */ + aSOI_SPAWN_TYPE_SPIRIT, /* pull from town spawns but force spirit if Wisp is active */ + + aSOI_SPAWN_TYPE_NUM +}; + +enum insect_spawn_category { + aSOI_SPAWN_CATEGORY_FG_ITEM_RANGE, + aSOI_SPAWN_CATEGORY_UT_ATTRIBUTE, + aSOI_SPAWN_CATEGORY_TREE, + aSOI_SPAWN_CATEGORY_UT_ATTRIBUTE_AND_FG_ITEM_RANGE, + + aSOI_SPAWN_CATEGORY_NUM +}; + +/** + * Insect term periods: + * TERM0: 11PM-4AM (5 hours) + * TERM1: 4AM-8AM (4 hours) + * TERM2: 8AM-4PM (8 hours) + * TERM3: 4PM-5PM (1 hour) + * TERM4: 5PM-7PM (2 hours) + * TERM5: 7PM-11PM (4 hours) + **/ + +#define aSOI_TERM0_START_HR 11+12 // 11:00PM +#define aSOI_TERM0_END_HR 3 // 03:59AM +#define aSOI_TERM1_START_HR 4 // 04:00AM +#define aSOI_TERM1_END_HR 7 // 07:59AM +#define aSOI_TERM2_START_HR 8 // 08:00AM +#define aSOI_TERM2_END_HR 3+12 // 03:59PM +#define aSOI_TERM3_START_HR 4+12 // 04:00PM +#define aSOI_TERM3_END_HR 4+12 // 04:59PM +#define aSOI_TERM4_START_HR 5+12 // 05:00PM +#define aSOI_TERM4_END_HR 6+12 // 06:59PM +#define aSOI_TERM5_START_HR 7+12 // 07:00PM +#define aSOI_TERM5_END_HR 10+12 // 10:59PM + +enum insect_term { + aSOI_TERM0, + aSOI_TERM1, + aSOI_TERM2, + aSOI_TERM3, + aSOI_TERM4, + aSOI_TERM5, + + aSOI_TERM_NUM +}; + extern int aSOI_insect_set(SET_MANAGER* set_manager, GAME_PLAY* play); #ifdef __cplusplus diff --git a/include/m_clip.h b/include/m_clip.h index 09220ffb..4c543995 100644 --- a/include/m_clip.h +++ b/include/m_clip.h @@ -3,6 +3,7 @@ #include "types.h" #include "ac_gyoei_h.h" +#include "ac_insect_h.h" #ifdef __cplusplus extern "C" { @@ -10,7 +11,9 @@ extern "C" { /* sizeof(Clip_c) == 0x104 */ typedef struct clip_s { - /* 0x000 */ void* _000[(0x0AC - 0x000) / sizeof(void*)]; + /* 0x000 */ void* _000[(0x07C - 0x000) / sizeof(void*)]; + /* 0x07C */ aINS_Clip_c* insect_clip; + /* 0x080 */ void* _080[(0x0AC - 0x080) / sizeof(void*)]; /* 0x0AC */ aGYO_Clip_c* gyo_clip; /* 0x0B0 */ void* _0B0[(0x104 - 0x0B0) / sizeof(void*)]; } Clip_c; diff --git a/include/m_collision_bg.h b/include/m_collision_bg.h index 03c44df0..9522ce69 100644 --- a/include/m_collision_bg.h +++ b/include/m_collision_bg.h @@ -10,9 +10,28 @@ extern "C" { enum background_attribute { /* TODO: finish */ + mCoBG_ATTRIBUTE_GRASS0, + mCoBG_ATTRIBUTE_GRASS1, + mCoBG_ATTRIBUTE_GRASS2, + mCoBG_ATTRIBUTE_GRASS3, + mCoBG_ATTRIBUTE_SOIL0, + mCoBG_ATTRIBUTE_SOIL1, + mCoBG_ATTRIBUTE_SOIL2, + mCoBG_ATTRIBUTE_BUSH = 9, mCoBG_ATTRIBUTE_WAVE = 11, - mCoBG_ATTRIBUTE_WATERFALL = 13, - mCoBG_ATTRIBUTE_SEA = 24 + mCoBG_ATTRIBUTE_WATER, + mCoBG_ATTRIBUTE_WATERFALL, + mCoBG_ATTRIBUTE_RIVER_N, + mCoBG_ATTRIBUTE_RIVER_NW, + mCoBG_ATTRIBUTE_RIVER_W, + mCoBG_ATTRIBUTE_RIVER_SW, + mCoBG_ATTRIBUTE_RIVER_S, + mCoBG_ATTRIBUTE_RIVER_SE, + mCoBG_ATTRIBUTE_RIVER_E, + mCoBG_ATTRIBUTE_RIVER_NE, + mCoBG_ATTRIBUTE_SAND, + mCoBG_ATTRIBUTE_WOOD, + mCoBG_ATTRIBUTE_SEA, }; /* sizeof(mCoBG_CollisionData_c) == 4*/ @@ -37,6 +56,7 @@ extern u32 mCoBG_Wpos2Attribute(xyz_t wpos, char* is_diggable); extern int mCoBG_CheckWaterAttribute(u32 attribute); extern f32 mCoBG_GetBgY_AngleS_FromWpos(s_xyz* angle_to_ground, xyz_t wpos, f32 offset); extern int mCoBG_CheckWaterAttribute_OutOfSea(u32 attribute); +extern int mCoBG_CheckHole_OrgAttr(u32 attribute); extern f32 mCoBG_GetWaterHeight_File(xyz_t wpos, char* file, int line); #define mCoBG_GetWaterHeight(wpos) mCoBG_GetWaterHeight_File(wpos, __FILE__, __LINE__) diff --git a/include/m_common_data.h b/include/m_common_data.h index 359709e1..c310b265 100644 --- a/include/m_common_data.h +++ b/include/m_common_data.h @@ -152,7 +152,11 @@ typedef struct common_data_s { /* 0x026144 */ u8 tmp0[0x2614D - 0x26144]; /* 0x02614D */ u8 transFadeDuration; /* 0x02614E */ u8 transWipeSpeed; - /* 0x02614F */ u8 tmp34[0x2852C - 0x2614F]; + /* 0x02614F */ u8 tmp34[0x2666C - 0x2614F]; + /* 0x02666C */ s16 weather; + /* 0x02666E */ s16 weather_intensity; + /* 0x026670 */ lbRTC_time_c weather_time; + /* 0x026678 */ u8 _26678[0x2852C - 0x26678]; /* 0x02852C */ s16 money_power; /* 0x02852E */ s16 goods_power; /* 0x028530 */ u8 tmp1[0x28879 - 0x28530]; diff --git a/include/m_event.h b/include/m_event.h index 128e3d02..c84c1580 100644 --- a/include/m_event.h +++ b/include/m_event.h @@ -112,6 +112,7 @@ enum event_table { mEv_EVENT_FISHING_TOURNEY_1 = 29, mEv_EVENT_MUSHROOM_SEASON = 47, mEv_EVENT_FISHING_TOURNEY_2 = 54, + mEv_EVENT_GHOST = 64, }; #define mEv_STATUS_ACTIVE (1 << 0) /* event is active */ @@ -122,10 +123,24 @@ enum event_table { #define mEv_STATUS_ERROR (1 << 5) /* event is in error state */ #define mEv_STATUS_TALK (1 << 6) /* event requires talking to player */ +#define mEv_GHOST_HITODAMA_NUM 5 +typedef struct ghost_spirit_block_data_s { + u8 block_x[mEv_GHOST_HITODAMA_NUM]; + u8 block_z[mEv_GHOST_HITODAMA_NUM]; +} mEv_gst_hitodama_block_c; + +#define mEv_GHOST_FLAG_ACTIVE 0x4000 // TODO: do these live in the ghost actor itself? +typedef struct ghost_common_s { + mEv_gst_hitodama_block_c hitodama_block_data; + u16 flags; + u8 _0C[0x2C - 0x0C]; +} mEv_gst_common_c; + extern int mEv_CheckFirstJob(); extern int mEv_CheckArbeit(); extern int mEv_CheckTitleDemo(); extern int mEv_check_status(int event, s16 status); +extern s8* mEv_get_common_area(int type, s8 id); extern int mEv_weekday2day(lbRTC_month_t month, int week_type, lbRTC_weekday_t weekday); diff --git a/include/m_field_info.h b/include/m_field_info.h index 163ee496..1e291c3f 100644 --- a/include/m_field_info.h +++ b/include/m_field_info.h @@ -87,6 +87,7 @@ 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 int mFI_GetLineDeposit(u16* deposit, int ut_x); +extern u16* mFI_GetDepositP(int block_x, int block_z); extern void mFI_GetSpecialBlockNum(int* block_pos_tbl, u32* kind_list, int kind_num); extern int mFI_SetTreasure(int* block_x, int* block_z, mActor_name_t item_no); extern void mFI_SetFGUpData(); @@ -97,6 +98,8 @@ extern void mFI_BkandUtNum2Wpos(xyz_t* wpos_p, int block_x, int block_z, int ut_ extern void mFI_BkandUtNum2CenterWpos(xyz_t* wpos_p, int block_x, int block_z, int ut_x, int ut_z); extern mCoBG_Collision_u* mFI_GetBkNum2ColTop(int block_x, int block_z); extern u32 mFI_BkNum2BlockKind(int block_x, int block_z); +extern int mFI_BlockKind2BkNum(int* block_x, int* block_z, u32 block_kind); +extern int mFI_GetBlockUtNum2FG(mActor_name_t* fg_item, int block_x, int block_z, int ut_x, int ut_z); extern void mFI_PrintNowBGNum(gfxprint_t* gfxprint); extern void mFI_PrintFgAttr(gfxprint_t* gfxprint); diff --git a/include/m_kankyo.h b/include/m_kankyo.h index eed56cb3..6050919e 100644 --- a/include/m_kankyo.h +++ b/include/m_kankyo.h @@ -8,13 +8,13 @@ extern "C" { #endif enum weather { - mEv_WEATHER_CLEAR, - mEv_WEATHER_RAIN, - mEv_WEATHER_SNOW, - mEv_WEATHER_SAKURA, - mEv_WEATHER_LEAVES, + mEnv_WEATHER_CLEAR, + mEnv_WEATHER_RAIN, + mEnv_WEATHER_SNOW, + mEnv_WEATHER_SAKURA, + mEnv_WEATHER_LEAVES, - mEv_WEATHER_NUM + mEnv_WEATHER_NUM }; extern int mEnv_NowWeather(); diff --git a/include/m_name_table.h b/include/m_name_table.h index ec66f7b7..eea1d071 100644 --- a/include/m_name_table.h +++ b/include/m_name_table.h @@ -143,6 +143,12 @@ extern int mNT_check_unknown(mActor_name_t item_no); #define TREE_PRESENT (TREE_LIGHTS + 1) #define TREE_BELLS 0x0069 +#define ROCK_A 0x0063 +#define ROCK_B (ROCK_A + 1) +#define ROCK_C (ROCK_B + 1) +#define ROCK_D (ROCK_C + 1) +#define ROCK_E (ROCK_D + 1) + #define CEDAR_TREE_BELLS 0x0078 #define CEDAR_TREE_FTR (CEDAR_TREE_BELLS + 1) #define CEDAR_TREE_BEES (CEDAR_TREE_FTR + 1) @@ -333,6 +339,7 @@ extern int mNT_check_unknown(mActor_name_t item_no); #define ITM_FOOD_START 0x2800 #define ITM_FOOD_MUSHROOM 0x2805 +#define ITM_FOOD_CANDY 0x2806 #define ITM_ENV_START 0x2900 #define ITM_SAPLING ITM_ENV_START @@ -349,6 +356,11 @@ extern int mNT_check_unknown(mActor_name_t item_no); #define ITM_COLLEGERULE 0x2B00 +#define ITM_KABU_10 0x2F00 +#define ITM_KABU_50 0x2F01 +#define ITM_KABU_100 0x2F02 +#define ITM_KABU_SPOILED 0x2F03 + #define FTR_ORANGEBOX 0x30F8 #define DOOR_START 0x4000 diff --git a/rel/ac_set_manager.c b/rel/ac_set_manager.c index 11f92c72..32d8cd61 100644 --- a/rel/ac_set_manager.c +++ b/rel/ac_set_manager.c @@ -113,7 +113,7 @@ static int aSetMgr_ovl(aSetMgr_set_ovl_c* set_ovl, int type) { * @param keep Pointer to the SET_MANAGER's internal aSetMgr_keep_c structure **/ static void aSetMgr_clear_keep(aSetMgr_keep_c* keep) { - bzero(keep, aSetMgr_KEEP_SIZE); + bzero(keep, sizeof(aSetMgr_keep_c)); } /** diff --git a/rel/ac_set_ovl_gyoei.c b/rel/ac_set_ovl_gyoei.c index a9774188..ddc4513d 100644 --- a/rel/ac_set_ovl_gyoei.c +++ b/rel/ac_set_ovl_gyoei.c @@ -1948,7 +1948,7 @@ static void aSOG_add_kaseki_range_data(aSOG_gyoei_keep_c* keep, int time_no, int static aSOG_gyoei_spawn_info_weight_f_c kaseki_data = FISH_SPAWN(COELACANTH, SEA, 2.0f); /* Only the current term, while raining, and not during 9am-3:59pm */ - if (is_next_term == FALSE && mEnv_NowWeather() == mEv_WEATHER_RAIN && time_no != aSOG_TIME_2) { + if (is_next_term == FALSE && mEnv_NowWeather() == mEnv_WEATHER_RAIN && time_no != aSOG_TIME_2) { keep->spawn_weights[keep->possible_gyoei_num] = kaseki_data; keep->possible_gyoei_num++; } diff --git a/rel/ac_set_ovl_insect.c b/rel/ac_set_ovl_insect.c new file mode 100644 index 00000000..658ccfc5 --- /dev/null +++ b/rel/ac_set_ovl_insect.c @@ -0,0 +1,2138 @@ +#include "ac_set_ovl_insect.h" +#include "m_field_info.h" +#include "m_field_make.h" +#include "m_random_field_h.h" +#include "m_name_table.h" +#include "libultra/libultra.h" +#include "libc64/qrand.h" +#include "m_common_data.h" +#include "m_time.h" +#include "m_event.h" +#include "m_field_assessment.h" +#include "m_kankyo.h" + +typedef struct insect_birth_sum_s { + u8 min_birth_count; + u8 additional_range; // min_birth_count + [0, n) +} aSOI_insect_birth_sum_c; + +static aSOI_insect_birth_sum_c l_insect_birth_sum[aSOI_INSECT_TYPE_EXTENDED_NUM] = { + { 1, 0 }, // aSOI_INSECT_TYPE_COMMON_BUTTERFLY + { 1, 0 }, // aSOI_INSECT_TYPE_YELLOW_BUTTERFLY + { 1, 0 }, // aSOI_INSECT_TYPE_TIGER_BUTTERFLY + { 1, 0 }, // aSOI_INSECT_TYPE_PURPLE_BUTTERFLY + { 1, 0 }, // aSOI_INSECT_TYPE_ROBUST_CICADA + { 1, 0 }, // aSOI_INSECT_TYPE_WALKER_CICADA + { 1, 0 }, // aSOI_INSECT_TYPE_EVENING_CICADA + { 1, 0 }, // aSOI_INSECT_TYPE_BROWN_CICADA + { 1, 0 }, // aSOI_INSECT_TYPE_BEE + { 1, 0 }, // aSOI_INSECT_TYPE_COMMON_DRAGONFLY + { 6, 3 }, // aSOI_INSECT_TYPE_RED_DRAGONFLY + { 1, 0 }, // aSOI_INSECT_TYPE_DARNER_DRAGONFLY + { 1, 0 }, // aSOI_INSECT_TYPE_BANDED_DRAGONFLY + { 1, 0 }, // aSOI_INSECT_TYPE_LONG_LOCUST + { 1, 0 }, // aSOI_INSECT_TYPE_MIGRATORY_LOCUST + { 1, 0 }, // aSOI_INSECT_TYPE_CRICKET + { 1, 0 }, // aSOI_INSECT_TYPE_GRASSHOPPER + { 1, 0 }, // aSOI_INSECT_TYPE_BELL_CRICKET + { 1, 0 }, // aSOI_INSECT_TYPE_PINE_CRICKET + { 1, 0 }, // aSOI_INSECT_TYPE_DRONE_BEETLE + { 1, 0 }, // aSOI_INSECT_TYPE_DYNASTID_BEETLE + { 1, 0 }, // aSOI_INSECT_TYPE_FLAT_STAG_BEETLE + { 1, 0 }, // aSOI_INSECT_TYPE_JEWEL_BEETLE + { 1, 0 }, // aSOI_INSECT_TYPE_LONGHORN_BEETLE + { 1, 0 }, // aSOI_INSECT_TYPE_LADYBUG + { 1, 0 }, // aSOI_INSECT_TYPE_SPOTTED_LADYBUG + { 1, 0 }, // aSOI_INSECT_TYPE_MANTIS + { 6, 3 }, // aSOI_INSECT_TYPE_FIREFLY + { 1, 0 }, // aSOI_INSECT_TYPE_COCKROACH + { 1, 0 }, // aSOI_INSECT_TYPE_SAW_STAG_BEETLE + { 1, 0 }, // aSOI_INSECT_TYPE_MOUNTAIN_BEETLE + { 1, 0 }, // aSOI_INSECT_TYPE_GIANT_BEETLE + { 1, 0 }, // aSOI_INSECT_TYPE_SNAIL + { 1, 0 }, // aSOI_INSECT_TYPE_MOLE_CRICKET + { 1, 0 }, // aSOI_INSECT_TYPE_POND_SKATER + { 1, 0 }, // aSOI_INSECT_TYPE_BAGWORM + { 1, 0 }, // aSOI_INSECT_TYPE_PILL_BUG + { 1, 0 }, // aSOI_INSECT_TYPE_SPIDER + { 1, 0 }, // aSOI_INSECT_TYPE_ANT + { 1, 0 }, // aSOI_INSECT_TYPE_MOSQUITO + { 1, 0 }, // aSOI_INSECT_TYPE_SPIRIT +}; + +/* sizeof(aSOI_term_info_c) == 0xC */ +typedef struct term_info_s { + /* 0x00 */ int type; /* insect type (aSOI_INSECT_TYPE_*) */ + /* 0x04 */ u8 spawn_area; /* spawn area (aSOI_SPAWN_AREA_*) */ + /* 0x05 */ u8 weight; /* weight value */ +} aSOI_term_info_c; + +/* sizeof (aSOI_term_list_c) == 8 */ +typedef struct term_list_s { + /* 0x00 */ u8 count; /* number of term info items */ + /* 0x04 */ aSOI_term_info_c* term_info; /* pointer to term info items */ +} aSOI_term_list_c; + +#define INSECT_SPAWN(insect, area, weight) { aSOI_INSECT_TYPE_##insect, aSOI_SPAWN_AREA_##area, weight } + +static aSOI_term_info_c l_insect_m3_t1[5] = { + INSECT_SPAWN(COCKROACH, ON_FLOWER, 1), /* 5.26% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 1), /* 5.26% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 26.32% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 10), /* 52.63% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 10.53% */ +}; + +static aSOI_term_info_c l_insect_m3_t2[5] = { + INSECT_SPAWN(COCKROACH, ON_FLOWER, 1), /* 5.26% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 1), /* 5.26% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 26.32% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 10), /* 52.63% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 10.53% */ +}; + +static aSOI_term_info_c l_insect_m3_t3[9] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 5), /* 8.47% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 5), /* 8.47% */ + INSECT_SPAWN(LADYBUG, ON_FLOWER, 15), /* 25.42% */ + INSECT_SPAWN(SPOTTED_LADYBUG, ON_FLOWER, 15), /* 25.42% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 1), /* 1.69% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 1), /* 1.69% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 8.47% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 10), /* 16.95% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 3.39% */ +}; + +static aSOI_term_info_c l_insect_m3_t4[7] = { + INSECT_SPAWN(LADYBUG, ON_FLOWER, 5), /* 17.24% */ + INSECT_SPAWN(SPOTTED_LADYBUG, ON_FLOWER, 5), /* 17.24% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 1), /* 3.45% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 1), /* 3.45% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 17.24% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 10), /* 34.48% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 6.90% */ +}; + +static aSOI_term_info_c l_insect_m3_t5[5] = { + INSECT_SPAWN(COCKROACH, ON_FLOWER, 1), /* 5.26% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 1), /* 5.26% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 26.32% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 10), /* 52.63% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 10.53% */ +}; + +static aSOI_term_info_c l_insect_m3_t6[5] = { + INSECT_SPAWN(COCKROACH, ON_FLOWER, 1), /* 5.26% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 1), /* 5.26% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 26.32% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 10), /* 52.63% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 10.53% */ +}; + +static aSOI_term_info_c l_insect_m4_t1[6] = { + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 8.00% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 8.00% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 20.00% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 10), /* 40.00% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 8.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 16.00% */ +}; + +static aSOI_term_info_c l_insect_m4_t2[6] = { + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 8.00% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 8.00% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 20.00% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 10), /* 40.00% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 8.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 16.00% */ +}; + +static aSOI_term_info_c l_insect_m4_t3[11] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 25), /* 25.00% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 24), /* 24.00% */ + INSECT_SPAWN(TIGER_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 2), /* 2.00% */ + INSECT_SPAWN(LADYBUG, ON_FLOWER, 12), /* 12.00% */ + INSECT_SPAWN(SPOTTED_LADYBUG, ON_FLOWER, 12), /* 12.00% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.00% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 5.00% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 10), /* 10.00% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 4.00% */ +}; + +static aSOI_term_info_c l_insect_m4_t4[10] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 5), /* 9.09% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 5), /* 9.09% */ + INSECT_SPAWN(LADYBUG, ON_FLOWER, 10), /* 18.18% */ + INSECT_SPAWN(SPOTTED_LADYBUG, ON_FLOWER, 10), /* 18.18% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 3.64% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 3.64% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 9.09% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 10), /* 18.18% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 3.64% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 7.27% */ +}; + +static aSOI_term_info_c l_insect_m4_t5[6] = { + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 8.00% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 8.00% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 20.00% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 10), /* 40.00% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 8.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 16.00% */ +}; + +static aSOI_term_info_c l_insect_m4_t6[6] = { + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 8.00% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 8.00% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 20.00% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 10), /* 40.00% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 8.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 16.00% */ +}; + +static aSOI_term_info_c l_insect_m5_t1[6] = { + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 11.11% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 11.11% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 27.78% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 3), /* 16.67% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 11.11% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 22.22% */ +}; + +static aSOI_term_info_c l_insect_m5_t2[6] = { + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 11.11% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 11.11% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 27.78% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 3), /* 16.67% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 11.11% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 22.22% */ +}; + +static aSOI_term_info_c l_insect_m5_t3[12] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 20), /* 20.00% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 20), /* 20.00% */ + INSECT_SPAWN(TIGER_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 5), /* 5.00% */ + INSECT_SPAWN(COMMON_DRAGONFLY, FLYING, 13), /* 13.00% */ + INSECT_SPAWN(LADYBUG, ON_FLOWER, 12), /* 12.00% */ + INSECT_SPAWN(SPOTTED_LADYBUG, ON_FLOWER, 12), /* 12.00% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.00% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 5.00% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 3), /* 3.00% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 4.00% */ +}; + +static aSOI_term_info_c l_insect_m5_t4[12] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 5), /* 7.81% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 5), /* 7.81% */ + INSECT_SPAWN(TIGER_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 1), /* 1.56% */ + INSECT_SPAWN(COMMON_DRAGONFLY, FLYING, 15), /* 23.44% */ + INSECT_SPAWN(LADYBUG, ON_FLOWER, 10), /* 15.62% */ + INSECT_SPAWN(SPOTTED_LADYBUG, ON_FLOWER, 10), /* 15.62% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 3.12% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 3.12% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 7.81% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 3), /* 4.69% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 3.12% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 6.25% */ +}; + +static aSOI_term_info_c l_insect_m5_t5[7] = { + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 10.00% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 10.00% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 25.00% */ + INSECT_SPAWN(MOSQUITO, FLYING, 2), /* 10.00% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 3), /* 15.00% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 10.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 20.00% */ +}; + +static aSOI_term_info_c l_insect_m5_t6[7] = { + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 10.53% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 10.53% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 26.32% */ + INSECT_SPAWN(MOSQUITO, FLYING, 1), /* 5.26% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 3), /* 15.79% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 10.53% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 21.05% */ +}; + +static aSOI_term_info_c l_insect_m6_t1[7] = { + INSECT_SPAWN(FLAT_STAG_BEETLE, ON_TREE, 2), /* 5.41% */ + INSECT_SPAWN(FIREFLY, FLYING_NEAR_WATER, 20), /* 54.05% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 5.41% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 5.41% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 13.51% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 5.41% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 10.81% */ +}; + +static aSOI_term_info_c l_insect_m6_t2[6] = { + INSECT_SPAWN(FLAT_STAG_BEETLE, ON_TREE, 2), /* 11.76% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 11.76% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 11.76% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 29.41% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 11.76% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 23.53% */ +}; + +static aSOI_term_info_c l_insect_m6_t3[15] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 15), /* 15.00% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 15), /* 15.00% */ + INSECT_SPAWN(TIGER_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 5), /* 5.00% */ + INSECT_SPAWN(PURPLE_BUTTERFLY, ON_TREE, 1), /* 1.00% */ + INSECT_SPAWN(COMMON_DRAGONFLY, FLYING, 21), /* 21.00% */ + INSECT_SPAWN(DARNER_DRAGONFLY, FLYING, 8), /* 8.00% */ + INSECT_SPAWN(LONGHORN_BEETLE, ON_TREE, 5), /* 5.00% */ + INSECT_SPAWN(LADYBUG, ON_FLOWER, 5), /* 5.00% */ + INSECT_SPAWN(SPOTTED_LADYBUG, ON_FLOWER, 5), /* 5.00% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.00% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(POND_SKATER, ON_WATER, 5), /* 5.00% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 5.00% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 4.00% */ +}; + +static aSOI_term_info_c l_insect_m6_t4[15] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 5), /* 6.10% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 5), /* 6.10% */ + INSECT_SPAWN(TIGER_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 1), /* 1.22% */ + INSECT_SPAWN(PURPLE_BUTTERFLY, ON_TREE, 1), /* 1.22% */ + INSECT_SPAWN(COMMON_DRAGONFLY, FLYING, 25), /* 30.49% */ + INSECT_SPAWN(DARNER_DRAGONFLY, FLYING, 10), /* 12.20% */ + INSECT_SPAWN(LONGHORN_BEETLE, ON_TREE, 5), /* 6.10% */ + INSECT_SPAWN(LADYBUG, ON_FLOWER, 5), /* 6.10% */ + INSECT_SPAWN(SPOTTED_LADYBUG, ON_FLOWER, 5), /* 6.10% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.44% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.44% */ + INSECT_SPAWN(POND_SKATER, ON_WATER, 5), /* 6.10% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 6.10% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.44% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 4.88% */ +}; + +static aSOI_term_info_c l_insect_m6_t5[7] = { + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 6.67% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 6.67% */ + INSECT_SPAWN(POND_SKATER, ON_WATER, 5), /* 16.67% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 16.67% */ + INSECT_SPAWN(MOSQUITO, FLYING, 10), /* 33.33% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 6.67% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 13.33% */ +}; + +static aSOI_term_info_c l_insect_m6_t6[8] = { + INSECT_SPAWN(FLAT_STAG_BEETLE, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(FIREFLY, FLYING_NEAR_WATER, 76), /* 76.00% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.00% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 5.00% */ + INSECT_SPAWN(MOSQUITO, FLYING, 7), /* 7.00% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 4.00% */ +}; + +static aSOI_term_info_c l_insect_m7_t1[11] = { + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 10), /* 21.74% */ + INSECT_SPAWN(DYNASTID_BEETLE, ON_TREE, 5), /* 10.87% */ + INSECT_SPAWN(FLAT_STAG_BEETLE, ON_TREE, 5), /* 10.87% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 4.35% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 4.35% */ + INSECT_SPAWN(SAW_STAG_BEETLE, ON_TREE, 5), /* 10.87% */ + INSECT_SPAWN(MOUNTAIN_BEETLE, ON_TREE, 5), /* 10.87% */ + INSECT_SPAWN(GIANT_BEETLE, ON_TREE, 1), /* 2.17% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 10.87% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 4.35% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 8.70% */ +}; + +static aSOI_term_info_c l_insect_m7_t2[12] = { + INSECT_SPAWN(EVENING_CICADA, ON_TREE, 10), /* 17.86% */ + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 10), /* 17.86% */ + INSECT_SPAWN(DYNASTID_BEETLE, ON_TREE, 5), /* 8.93% */ + INSECT_SPAWN(FLAT_STAG_BEETLE, ON_TREE, 5), /* 8.93% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 3.57% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 3.57% */ + INSECT_SPAWN(SAW_STAG_BEETLE, ON_TREE, 5), /* 8.93% */ + INSECT_SPAWN(MOUNTAIN_BEETLE, ON_TREE, 5), /* 8.93% */ + INSECT_SPAWN(GIANT_BEETLE, ON_TREE, 1), /* 1.79% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 8.93% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 3.57% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 7.14% */ +}; + +static aSOI_term_info_c l_insect_m7_t3[21] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 3), /* 3.95% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 3), /* 3.95% */ + INSECT_SPAWN(TIGER_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 3), /* 3.95% */ + INSECT_SPAWN(PURPLE_BUTTERFLY, ON_TREE, 2), /* 2.63% */ + INSECT_SPAWN(ROBUST_CICADA, ON_TREE, 5), /* 6.58% */ + INSECT_SPAWN(WALKER_CICADA, ON_TREE, 2), /* 2.63% */ + INSECT_SPAWN(BROWN_CICADA, ON_TREE, 6), /* 7.89% */ + INSECT_SPAWN(COMMON_DRAGONFLY, FLYING, 8), /* 10.53% */ + INSECT_SPAWN(DARNER_DRAGONFLY, FLYING, 5), /* 6.58% */ + INSECT_SPAWN(BANDED_DRAGONFLY, FLYING, 5), /* 6.58% */ + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 4), /* 5.26% */ + INSECT_SPAWN(JEWEL_BEETLE, ON_TREE, 2), /* 2.63% */ + INSECT_SPAWN(LONGHORN_BEETLE, ON_TREE, 4), /* 5.26% */ + INSECT_SPAWN(LADYBUG, ON_FLOWER, 2), /* 2.63% */ + INSECT_SPAWN(SPOTTED_LADYBUG, ON_FLOWER, 2), /* 2.63% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.63% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.63% */ + INSECT_SPAWN(POND_SKATER, ON_WATER, 5), /* 6.58% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 6.58% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.63% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 5.26% */ +}; + +static aSOI_term_info_c l_insect_m7_t4[19] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 3), /* 3.90% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 3), /* 3.90% */ + INSECT_SPAWN(TIGER_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 1), /* 1.30% */ + INSECT_SPAWN(PURPLE_BUTTERFLY, ON_TREE, 1), /* 1.30% */ + INSECT_SPAWN(EVENING_CICADA, ON_TREE, 10), /* 12.99% */ + INSECT_SPAWN(BROWN_CICADA, ON_TREE, 1), /* 1.30% */ + INSECT_SPAWN(COMMON_DRAGONFLY, FLYING, 8), /* 10.39% */ + INSECT_SPAWN(DARNER_DRAGONFLY, FLYING, 5), /* 6.49% */ + INSECT_SPAWN(BANDED_DRAGONFLY, FLYING, 5), /* 6.49% */ + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 8), /* 10.39% */ + INSECT_SPAWN(LONGHORN_BEETLE, ON_TREE, 5), /* 6.49% */ + INSECT_SPAWN(LADYBUG, ON_FLOWER, 3), /* 3.90% */ + INSECT_SPAWN(SPOTTED_LADYBUG, ON_FLOWER, 2), /* 2.60% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.60% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.60% */ + INSECT_SPAWN(POND_SKATER, ON_WATER, 7), /* 9.09% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 6.49% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.60% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 5.19% */ +}; + +static aSOI_term_info_c l_insect_m7_t5[9] = { + INSECT_SPAWN(EVENING_CICADA, ON_TREE, 15), /* 22.06% */ + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 10), /* 14.71% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.94% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.94% */ + INSECT_SPAWN(POND_SKATER, ON_WATER, 8), /* 11.76% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 7.35% */ + INSECT_SPAWN(MOSQUITO, FLYING, 20), /* 29.41% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.94% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 5.88% */ +}; + +static aSOI_term_info_c l_insect_m7_t6[11] = { + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 10), /* 16.67% */ + INSECT_SPAWN(DYNASTID_BEETLE, ON_TREE, 5), /* 8.33% */ + INSECT_SPAWN(FLAT_STAG_BEETLE, ON_TREE, 5), /* 8.33% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 3.33% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 3.33% */ + INSECT_SPAWN(SAW_STAG_BEETLE, ON_TREE, 5), /* 8.33% */ + INSECT_SPAWN(MOUNTAIN_BEETLE, ON_TREE, 5), /* 8.33% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 8.33% */ + INSECT_SPAWN(MOSQUITO, FLYING, 15), /* 25.00% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 3.33% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 6.67% */ +}; + +static aSOI_term_info_c l_insect_m8_t1[11] = { + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 10), /* 21.74% */ + INSECT_SPAWN(DYNASTID_BEETLE, ON_TREE, 5), /* 10.87% */ + INSECT_SPAWN(FLAT_STAG_BEETLE, ON_TREE, 5), /* 10.87% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 4.35% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 4.35% */ + INSECT_SPAWN(SAW_STAG_BEETLE, ON_TREE, 5), /* 10.87% */ + INSECT_SPAWN(MOUNTAIN_BEETLE, ON_TREE, 5), /* 10.87% */ + INSECT_SPAWN(GIANT_BEETLE, ON_TREE, 1), /* 2.17% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 10.87% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 4.35% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 8.70% */ +}; + +static aSOI_term_info_c l_insect_m8_t2[12] = { + INSECT_SPAWN(EVENING_CICADA, ON_TREE, 10), /* 16.39% */ + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 15), /* 24.59% */ + INSECT_SPAWN(DYNASTID_BEETLE, ON_TREE, 5), /* 8.20% */ + INSECT_SPAWN(FLAT_STAG_BEETLE, ON_TREE, 5), /* 8.20% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 3.28% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 3.28% */ + INSECT_SPAWN(SAW_STAG_BEETLE, ON_TREE, 5), /* 8.20% */ + INSECT_SPAWN(MOUNTAIN_BEETLE, ON_TREE, 5), /* 8.20% */ + INSECT_SPAWN(GIANT_BEETLE, ON_TREE, 1), /* 1.64% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 8.20% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 3.28% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 6.56% */ +}; + +static aSOI_term_info_c l_insect_m8_t3[21] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 3), /* 3.85% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 2), /* 2.56% */ + INSECT_SPAWN(TIGER_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 3), /* 3.85% */ + INSECT_SPAWN(PURPLE_BUTTERFLY, ON_TREE, 2), /* 2.56% */ + INSECT_SPAWN(ROBUST_CICADA, ON_TREE, 4), /* 5.13% */ + INSECT_SPAWN(WALKER_CICADA, ON_TREE, 3), /* 3.85% */ + INSECT_SPAWN(BROWN_CICADA, ON_TREE, 4), /* 5.13% */ + INSECT_SPAWN(BANDED_DRAGONFLY, FLYING, 5), /* 6.41% */ + INSECT_SPAWN(DARNER_DRAGONFLY, FLYING, 5), /* 6.41% */ + INSECT_SPAWN(LONG_LOCUST, ON_GROUND, 3), /* 3.85% */ + INSECT_SPAWN(GRASSHOPPER, IN_BUSH, 8), /* 10.26% */ + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 4), /* 5.13% */ + INSECT_SPAWN(JEWEL_BEETLE, ON_TREE, 2), /* 2.56% */ + INSECT_SPAWN(LONGHORN_BEETLE, ON_TREE, 3), /* 3.85% */ + INSECT_SPAWN(MANTIS, ON_FLOWER, 4), /* 5.13% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.56% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.56% */ + INSECT_SPAWN(POND_SKATER, ON_WATER, 8), /* 10.26% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 6.41% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.56% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 5.13% */ +}; + +static aSOI_term_info_c l_insect_m8_t4[19] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 3), /* 3.75% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 3), /* 3.75% */ + INSECT_SPAWN(TIGER_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 1), /* 1.25% */ + INSECT_SPAWN(PURPLE_BUTTERFLY, ON_TREE, 1), /* 1.25% */ + INSECT_SPAWN(EVENING_CICADA, ON_TREE, 9), /* 11.25% */ + INSECT_SPAWN(BROWN_CICADA, ON_TREE, 1), /* 1.25% */ + INSECT_SPAWN(DARNER_DRAGONFLY, FLYING, 5), /* 6.25% */ + INSECT_SPAWN(BANDED_DRAGONFLY, FLYING, 5), /* 6.25% */ + INSECT_SPAWN(LONG_LOCUST, ON_GROUND, 3), /* 3.75% */ + INSECT_SPAWN(GRASSHOPPER, IN_BUSH, 8), /* 10.00% */ + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 9), /* 11.25% */ + INSECT_SPAWN(LONGHORN_BEETLE, ON_TREE, 3), /* 3.75% */ + INSECT_SPAWN(MANTIS, ON_FLOWER, 4), /* 5.00% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.50% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.50% */ + INSECT_SPAWN(POND_SKATER, ON_WATER, 10), /* 12.50% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 6.25% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.50% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 5.00% */ +}; + +static aSOI_term_info_c l_insect_m8_t5[10] = { + INSECT_SPAWN(EVENING_CICADA, ON_TREE, 14), /* 19.44% */ + INSECT_SPAWN(LONG_LOCUST, ON_GROUND, 3), /* 4.17% */ + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 10), /* 13.89% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.78% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.78% */ + INSECT_SPAWN(POND_SKATER, ON_WATER, 10), /* 13.89% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 6.94% */ + INSECT_SPAWN(MOSQUITO, FLYING, 20), /* 27.78% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.78% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 5.56% */ +}; + +static aSOI_term_info_c l_insect_m8_t6[11] = { + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 10), /* 16.67% */ + INSECT_SPAWN(DYNASTID_BEETLE, ON_TREE, 5), /* 8.33% */ + INSECT_SPAWN(FLAT_STAG_BEETLE, ON_TREE, 5), /* 8.33% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 3.33% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 3.33% */ + INSECT_SPAWN(SAW_STAG_BEETLE, ON_TREE, 5), /* 8.33% */ + INSECT_SPAWN(MOUNTAIN_BEETLE, ON_TREE, 5), /* 8.33% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 8.33% */ + INSECT_SPAWN(MOSQUITO, FLYING, 15), /* 25.00% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 3.33% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 6.67% */ +}; + +static aSOI_term_info_c l_insect_m9_t1[8] = { + INSECT_SPAWN(CRICKET, IN_BUSH, 43), /* 43.00% */ + INSECT_SPAWN(BELL_CRICKET, IN_BUSH, 15), /* 15.00% */ + INSECT_SPAWN(PINE_CRICKET, IN_BUSH, 27), /* 27.00% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.00% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 5.00% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 4.00% */ +}; + +static aSOI_term_info_c l_insect_m9_t2[8] = { + INSECT_SPAWN(CRICKET, IN_BUSH, 20), /* 46.51% */ + INSECT_SPAWN(BELL_CRICKET, IN_BUSH, 3), /* 6.98% */ + INSECT_SPAWN(PINE_CRICKET, IN_BUSH, 5), /* 11.63% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 4.65% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 4.65% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 11.63% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 4.65% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 9.30% */ +}; + +static aSOI_term_info_c l_insect_m9_t3[15] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 3), /* 3.09% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 3), /* 3.09% */ + INSECT_SPAWN(TIGER_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 3), /* 3.09% */ + INSECT_SPAWN(WALKER_CICADA, ON_TREE, 2), /* 2.06% */ + INSECT_SPAWN(RED_DRAGONFLY, FLYING, 5), /* 5.15% */ + INSECT_SPAWN(LONG_LOCUST, ON_GROUND, 19), /* 19.59% */ + INSECT_SPAWN(MIGRATORY_LOCUST, ON_GROUND, 19), /* 19.59% */ + INSECT_SPAWN(GRASSHOPPER, IN_BUSH, 11), /* 11.34% */ + INSECT_SPAWN(MANTIS, ON_FLOWER, 14), /* 14.43% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.06% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.06% */ + INSECT_SPAWN(POND_SKATER, ON_WATER, 3), /* 3.09% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 5.15% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.06% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 4.12% */ +}; + +static aSOI_term_info_c l_insect_m9_t4[11] = { + INSECT_SPAWN(RED_DRAGONFLY, FLYING, 50), /* 50.00% */ + INSECT_SPAWN(LONG_LOCUST, ON_GROUND, 10), /* 10.00% */ + INSECT_SPAWN(MIGRATORY_LOCUST, ON_GROUND, 10), /* 10.00% */ + INSECT_SPAWN(GRASSHOPPER, IN_BUSH, 5), /* 5.00% */ + INSECT_SPAWN(MANTIS, ON_FLOWER, 5), /* 5.00% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.00% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(POND_SKATER, ON_WATER, 5), /* 5.00% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 5.00% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 4.00% */ +}; + +static aSOI_term_info_c l_insect_m9_t5[13] = { + INSECT_SPAWN(RED_DRAGONFLY, FLYING, 5), /* 6.41% */ + INSECT_SPAWN(LONG_LOCUST, ON_GROUND, 10), /* 12.82% */ + INSECT_SPAWN(MIGRATORY_LOCUST, ON_GROUND, 10), /* 12.82% */ + INSECT_SPAWN(CRICKET, IN_BUSH, 20), /* 25.64% */ + INSECT_SPAWN(BELL_CRICKET, IN_BUSH, 3), /* 3.85% */ + INSECT_SPAWN(PINE_CRICKET, IN_BUSH, 5), /* 6.41% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.56% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.56% */ + INSECT_SPAWN(POND_SKATER, ON_WATER, 5), /* 6.41% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 6.41% */ + INSECT_SPAWN(MOSQUITO, FLYING, 5), /* 6.41% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.56% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 5.13% */ +}; + +static aSOI_term_info_c l_insect_m9_t6[9] = { + INSECT_SPAWN(CRICKET, IN_BUSH, 40), /* 40.00% */ + INSECT_SPAWN(BELL_CRICKET, IN_BUSH, 15), /* 15.00% */ + INSECT_SPAWN(PINE_CRICKET, IN_BUSH, 28), /* 28.00% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.00% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 5.00% */ + INSECT_SPAWN(MOSQUITO, FLYING, 2), /* 2.00% */ + INSECT_SPAWN(SPIDER, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 4), /* 4.00% */ +}; + +static aSOI_term_info_c l_insect_m10_t1[7] = { + INSECT_SPAWN(CRICKET, IN_BUSH, 30), /* 42.25% */ + INSECT_SPAWN(BELL_CRICKET, IN_BUSH, 10), /* 14.08% */ + INSECT_SPAWN(PINE_CRICKET, IN_BUSH, 20), /* 28.17% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.82% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.82% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 7.04% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 2.82% */ +}; + +static aSOI_term_info_c l_insect_m10_t2[7] = { + INSECT_SPAWN(CRICKET, IN_BUSH, 5), /* 20.83% */ + INSECT_SPAWN(BELL_CRICKET, IN_BUSH, 3), /* 12.50% */ + INSECT_SPAWN(PINE_CRICKET, IN_BUSH, 5), /* 20.83% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 8.33% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 8.33% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 20.83% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 8.33% */ +}; + +static aSOI_term_info_c l_insect_m10_t3[12] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 3), /* 3.66% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 3), /* 3.66% */ + INSECT_SPAWN(RED_DRAGONFLY, FLYING, 5), /* 6.10% */ + INSECT_SPAWN(LONG_LOCUST, ON_GROUND, 15), /* 18.29% */ + INSECT_SPAWN(MIGRATORY_LOCUST, ON_GROUND, 15), /* 18.29% */ + INSECT_SPAWN(LADYBUG, ON_FLOWER, 10), /* 12.20% */ + INSECT_SPAWN(SPOTTED_LADYBUG, ON_FLOWER, 10), /* 12.20% */ + INSECT_SPAWN(MANTIS, ON_FLOWER, 10), /* 12.20% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.44% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.44% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 6.10% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 2.44% */ +}; + +static aSOI_term_info_c l_insect_m10_t4[10] = { + INSECT_SPAWN(RED_DRAGONFLY, FLYING, 54), /* 54.00% */ + INSECT_SPAWN(LONG_LOCUST, ON_GROUND, 10), /* 10.00% */ + INSECT_SPAWN(MIGRATORY_LOCUST, ON_GROUND, 10), /* 10.00% */ + INSECT_SPAWN(LADYBUG, ON_FLOWER, 5), /* 5.00% */ + INSECT_SPAWN(SPOTTED_LADYBUG, ON_FLOWER, 5), /* 5.00% */ + INSECT_SPAWN(MANTIS, ON_FLOWER, 5), /* 5.00% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.00% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 5.00% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 2.00% */ +}; + +static aSOI_term_info_c l_insect_m10_t5[10] = { + INSECT_SPAWN(RED_DRAGONFLY, FLYING, 5), /* 12.82% */ + INSECT_SPAWN(LONG_LOCUST, ON_GROUND, 5), /* 12.82% */ + INSECT_SPAWN(MIGRATORY_LOCUST, ON_GROUND, 5), /* 12.82% */ + INSECT_SPAWN(CRICKET, IN_BUSH, 5), /* 12.82% */ + INSECT_SPAWN(BELL_CRICKET, IN_BUSH, 3), /* 7.69% */ + INSECT_SPAWN(PINE_CRICKET, IN_BUSH, 5), /* 12.82% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 5.13% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 5.13% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 12.82% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 5.13% */ +}; + +static aSOI_term_info_c l_insect_m10_t6[7] = { + INSECT_SPAWN(CRICKET, IN_BUSH, 30), /* 42.25% */ + INSECT_SPAWN(BELL_CRICKET, IN_BUSH, 10), /* 14.08% */ + INSECT_SPAWN(PINE_CRICKET, IN_BUSH, 20), /* 28.17% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 2), /* 2.82% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 2), /* 2.82% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 7.04% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 2.82% */ +}; + +static aSOI_term_info_c l_insect_m11_t1[6] = { + INSECT_SPAWN(CRICKET, IN_BUSH, 10), /* 45.45% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 1), /* 4.55% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 1), /* 4.55% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 22.73% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 3), /* 13.64% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 9.09% */ +}; + +static aSOI_term_info_c l_insect_m11_t2[6] = { + INSECT_SPAWN(CRICKET, IN_BUSH, 3), /* 20.00% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 1), /* 6.67% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 1), /* 6.67% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 33.33% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 3), /* 20.00% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 13.33% */ +}; + +static aSOI_term_info_c l_insect_m11_t3[7] = { + INSECT_SPAWN(LONG_LOCUST, ON_GROUND, 5), /* 22.73% */ + INSECT_SPAWN(MIGRATORY_LOCUST, ON_GROUND, 5), /* 22.73% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 1), /* 4.55% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 1), /* 4.55% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 22.73% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 3), /* 13.64% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 9.09% */ +}; + +static aSOI_term_info_c l_insect_m11_t4[7] = { + INSECT_SPAWN(LONG_LOCUST, ON_GROUND, 5), /* 22.73% */ + INSECT_SPAWN(MIGRATORY_LOCUST, ON_GROUND, 5), /* 22.73% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 1), /* 4.55% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 1), /* 4.55% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 22.73% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 3), /* 13.64% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 9.09% */ +}; + +static aSOI_term_info_c l_insect_m11_t5[6] = { + INSECT_SPAWN(CRICKET, IN_BUSH, 3), /* 20.00% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 1), /* 6.67% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 1), /* 6.67% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 33.33% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 3), /* 20.00% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 13.33% */ +}; + +static aSOI_term_info_c l_insect_m11_t6[6] = { + INSECT_SPAWN(CRICKET, IN_BUSH, 10), /* 45.45% */ + INSECT_SPAWN(COCKROACH, ON_FLOWER, 1), /* 4.55% */ + INSECT_SPAWN(COCKROACH, ON_TREE, 1), /* 4.55% */ + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 22.73% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 3), /* 13.64% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 9.09% */ +}; + +static aSOI_term_info_c l_insect_m_other_t[3] = { + INSECT_SPAWN(PILL_BUG, UNDER_ROCK, 5), /* 29.41% */ + INSECT_SPAWN(MOLE_CRICKET, UNDERGROUND, 10), /* 58.82% */ + INSECT_SPAWN(BAGWORM, ON_TREE, 2), /* 11.76% */ +}; + +static aSOI_term_info_c l_insect_isl_t1[8] = { + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 6), /* 6.12% */ + INSECT_SPAWN(DYNASTID_BEETLE, ON_TREE, 3), /* 3.06% */ + INSECT_SPAWN(FLAT_STAG_BEETLE, ON_TREE, 3), /* 3.06% */ + INSECT_SPAWN(SAW_STAG_BEETLE, ON_TREE, 2), /* 2.04% */ + INSECT_SPAWN(MOUNTAIN_BEETLE, ON_TREE, 2), /* 2.04% */ + INSECT_SPAWN(GIANT_BEETLE, ON_TREE, 1), /* 1.02% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 3), /* 3.06% */ + INSECT_SPAWN(NONE, NOTHING, 78), /* 79.59% */ +}; + +static aSOI_term_info_c l_insect_isl_t2[9] = { + INSECT_SPAWN(EVENING_CICADA, ON_TREE, 30), /* 30.00% */ + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 8), /* 8.00% */ + INSECT_SPAWN(DYNASTID_BEETLE, ON_TREE, 3), /* 3.00% */ + INSECT_SPAWN(FLAT_STAG_BEETLE, ON_TREE, 3), /* 3.00% */ + INSECT_SPAWN(SAW_STAG_BEETLE, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(MOUNTAIN_BEETLE, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(GIANT_BEETLE, ON_TREE, 1), /* 1.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 3), /* 3.00% */ + INSECT_SPAWN(NONE, NOTHING, 48), /* 48.00% */ +}; + +static aSOI_term_info_c l_insect_isl_t3[17] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 8), /* 7.41% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 8), /* 7.41% */ + INSECT_SPAWN(TIGER_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 10), /* 9.26% */ + INSECT_SPAWN(PURPLE_BUTTERFLY, ON_TREE, 6), /* 5.56% */ + INSECT_SPAWN(ROBUST_CICADA, ON_TREE, 10), /* 9.26% */ + INSECT_SPAWN(WALKER_CICADA, ON_TREE, 8), /* 7.41% */ + INSECT_SPAWN(BROWN_CICADA, ON_TREE, 18), /* 16.67% */ + INSECT_SPAWN(DARNER_DRAGONFLY, FLYING, 5), /* 4.63% */ + INSECT_SPAWN(BANDED_DRAGONFLY, FLYING, 5), /* 4.63% */ + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 3), /* 2.78% */ + INSECT_SPAWN(JEWEL_BEETLE, ON_TREE, 2), /* 1.85% */ + INSECT_SPAWN(LONGHORN_BEETLE, ON_TREE, 3), /* 2.78% */ + INSECT_SPAWN(LADYBUG, ON_FLOWER, 4), /* 3.70% */ + INSECT_SPAWN(SPOTTED_LADYBUG, ON_FLOWER, 4), /* 3.70% */ + INSECT_SPAWN(MANTIS, ON_FLOWER, 4), /* 3.70% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 3), /* 2.78% */ + INSECT_SPAWN(NONE, NOTHING, 7), /* 6.48% */ +}; + +static aSOI_term_info_c l_insect_isl_t4[15] = { + INSECT_SPAWN(COMMON_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 8), /* 8.00% */ + INSECT_SPAWN(YELLOW_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 8), /* 8.00% */ + INSECT_SPAWN(TIGER_BUTTERFLY, FLYING_NEAR_FLOWERS_OR_AROUND, 10), /* 10.00% */ + INSECT_SPAWN(PURPLE_BUTTERFLY, ON_TREE, 5), /* 5.00% */ + INSECT_SPAWN(EVENING_CICADA, ON_TREE, 27), /* 27.00% */ + INSECT_SPAWN(BROWN_CICADA, ON_TREE, 3), /* 3.00% */ + INSECT_SPAWN(DARNER_DRAGONFLY, FLYING, 5), /* 5.00% */ + INSECT_SPAWN(BANDED_DRAGONFLY, FLYING, 5), /* 5.00% */ + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 6), /* 6.00% */ + INSECT_SPAWN(LONGHORN_BEETLE, ON_TREE, 3), /* 3.00% */ + INSECT_SPAWN(LADYBUG, ON_FLOWER, 4), /* 4.00% */ + INSECT_SPAWN(SPOTTED_LADYBUG, ON_FLOWER, 4), /* 4.00% */ + INSECT_SPAWN(MANTIS, ON_FLOWER, 4), /* 4.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 3), /* 3.00% */ + INSECT_SPAWN(NONE, NOTHING, 5), /* 5.00% */ +}; + +static aSOI_term_info_c l_insect_isl_t5[5] = { + INSECT_SPAWN(EVENING_CICADA, ON_TREE, 42), /* 42.00% */ + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 8), /* 8.00% */ + INSECT_SPAWN(MOSQUITO, FLYING, 10), /* 10.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 3), /* 3.00% */ + INSECT_SPAWN(NONE, NOTHING, 37), /* 37.00% */ +}; + +static aSOI_term_info_c l_insect_isl_t6[8] = { + INSECT_SPAWN(DRONE_BEETLE, ON_TREE, 8), /* 8.00% */ + INSECT_SPAWN(DYNASTID_BEETLE, ON_TREE, 3), /* 3.00% */ + INSECT_SPAWN(FLAT_STAG_BEETLE, ON_TREE, 3), /* 3.00% */ + INSECT_SPAWN(SAW_STAG_BEETLE, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(MOUNTAIN_BEETLE, ON_TREE, 2), /* 2.00% */ + INSECT_SPAWN(MOSQUITO, FLYING, 7), /* 7.00% */ + INSECT_SPAWN(SNAIL, RAINING_ON_FLOWER, 3), /* 3.00% */ + INSECT_SPAWN(NONE, NOTHING, 72), /* 72.00% */ +}; + +static aSOI_term_info_c l_hitodama_time_table = INSECT_SPAWN(SPIRIT, FLYING, 100); + +static aSOI_term_list_c l_insect_month[lbRTC_MONTHS_MAX][aSOI_TERM_NUM] = { + // January + { + { 3, l_insect_m_other_t }, // t1 + { 3, l_insect_m_other_t }, // t2 + { 3, l_insect_m_other_t }, // t3 + { 3, l_insect_m_other_t }, // t4 + { 3, l_insect_m_other_t }, // t5 + { 3, l_insect_m_other_t }, // t6 + }, + + // February + { + { 3, l_insect_m_other_t }, // t1 + { 3, l_insect_m_other_t }, // t2 + { 3, l_insect_m_other_t }, // t3 + { 3, l_insect_m_other_t }, // t4 + { 3, l_insect_m_other_t }, // t5 + { 3, l_insect_m_other_t }, // t6 + }, + + // March + { + { 5, l_insect_m3_t1 }, + { 5, l_insect_m3_t2 }, + { 9, l_insect_m3_t3 }, + { 7, l_insect_m3_t4 }, + { 5, l_insect_m3_t5 }, + { 5, l_insect_m3_t6 }, + }, + + // April + { + { 6, l_insect_m4_t1 }, + { 6, l_insect_m4_t2 }, + { 11, l_insect_m4_t3 }, + { 10, l_insect_m4_t4 }, + { 6, l_insect_m4_t5 }, + { 6, l_insect_m4_t6 }, + }, + + // May + { + { 6, l_insect_m5_t1 }, + { 6, l_insect_m5_t2 }, + { 12, l_insect_m5_t3 }, + { 12, l_insect_m5_t4 }, + { 7, l_insect_m5_t5 }, + { 7, l_insect_m5_t6 }, + }, + + // June + { + { 7, l_insect_m6_t1 }, + { 6, l_insect_m6_t2 }, + { 15, l_insect_m6_t3 }, + { 15, l_insect_m6_t4 }, + { 7, l_insect_m6_t5 }, + { 8, l_insect_m6_t6 }, + }, + + // July + { + { 11, l_insect_m7_t1 }, + { 12, l_insect_m7_t2 }, + { 21, l_insect_m7_t3 }, + { 19, l_insect_m7_t4 }, + { 9, l_insect_m7_t5 }, + { 11, l_insect_m7_t6 }, + }, + + // August + { + { 11, l_insect_m8_t1 }, + { 12, l_insect_m8_t2 }, + { 21, l_insect_m8_t3 }, + { 19, l_insect_m8_t4 }, + { 10, l_insect_m8_t5 }, + { 11, l_insect_m8_t6 }, + }, + + // September + { + { 8, l_insect_m9_t1 }, + { 8, l_insect_m9_t2 }, + { 15, l_insect_m9_t3 }, + { 11, l_insect_m9_t4 }, + { 13, l_insect_m9_t5 }, + { 9, l_insect_m9_t6 }, + }, + + // October + { + { 7, l_insect_m10_t1 }, + { 7, l_insect_m10_t2 }, + { 12, l_insect_m10_t3 }, + { 10, l_insect_m10_t4 }, + { 10, l_insect_m10_t5 }, + { 7, l_insect_m10_t6 }, + }, + + // November + { + { 6, l_insect_m11_t1 }, + { 6, l_insect_m11_t2 }, + { 7, l_insect_m11_t3 }, + { 7, l_insect_m11_t4 }, + { 6, l_insect_m11_t5 }, + { 6, l_insect_m11_t6 }, + }, + + // December + { + { 3, l_insect_m_other_t }, // t1 + { 3, l_insect_m_other_t }, // t2 + { 3, l_insect_m_other_t }, // t3 + { 3, l_insect_m_other_t }, // t4 + { 3, l_insect_m_other_t }, // t5 + { 3, l_insect_m_other_t }, // t6 + }, +}; + +static aSOI_term_list_c l_insect_island[aSOI_TERM_NUM] = { + { 8, l_insect_isl_t1 }, + { 9, l_insect_isl_t2 }, + { 17, l_insect_isl_t3 }, + { 15, l_insect_isl_t4 }, + { 5, l_insect_isl_t5 }, + { 8, l_insect_isl_t6 }, +}; + +typedef struct insect_set_data_s { + u8 type; + u8 ut_x; + u8 ut_z; + u8 should_spawn; + int extra_data; + u16 live_ut[UT_Z_NUM - 4]; + int num_live_ut; +} aSOI_set_data_c; + +static void aSOI_ins_clear_set_data(aSOI_set_data_c* set_data) { + set_data->type = 0; /* should this be aSOI_INSECT_TYPE_COMMON_BUTTERFLY? */ + set_data->ut_x = -1; + set_data->ut_z = -1; + set_data->should_spawn = FALSE; + set_data->extra_data = -1; + bzero(set_data->live_ut, (UT_Z_NUM - 4) * sizeof(u16)); + set_data->num_live_ut = 0; +} + +static void aSOI_set_live_ut(aSOI_set_data_c* set_data, int ut_x, int ut_z, int set) { + set_data->live_ut[ut_z - 2] = (u16)(set_data->live_ut[ut_z - 2] & ~(1 << ut_x)) | (set << ut_x); + + if (set == TRUE) { + set_data->num_live_ut++; + return; + } + + set_data->num_live_ut--; + if (set_data->num_live_ut >= 0) { + return; + } + + set_data->num_live_ut = 0; +} + +static int aSOI_get_live_ut_sub(aSOI_set_data_c* set_data, int ut_x, int ut_z) { + int res = FALSE; + if ((set_data->live_ut[ut_z - 2] >> ut_x) & 1) { + res = TRUE; + } + return res; +} + +static int aSOI_get_live_ut(aSOI_set_data_c* set_data, int* ut_x_out, int* ut_z_out) { + int z; + int x; + int selected; + if (set_data->num_live_ut <= 0) { + return FALSE; + } + + selected = (int)(fqrand() * (f32)set_data->num_live_ut); + + for (z = 2; z < UT_Z_NUM - 2; z++) { + for (x = 2; x < UT_X_NUM - 2; x++) { + if (aSOI_get_live_ut_sub(set_data, x, z) == TRUE) { + if (selected <= 0) { + *ut_x_out = x; + *ut_z_out = z; + aSOI_set_live_ut(set_data, x, z, FALSE); // remove unit from "set" units + return TRUE; + } + + selected--; + } + } + } + + return FALSE; +} + +static int aSOI_hour_to_term(int hour) { + int term = aSOI_TERM0; + if (hour >= aSOI_TERM1_START_HR) { + if (hour < aSOI_TERM2_START_HR) { + term = aSOI_TERM1; + } + else if (hour < aSOI_TERM3_START_HR) { + term = aSOI_TERM2; + } + else if (hour < aSOI_TERM4_START_HR) { + term = aSOI_TERM3; + } + else if (hour < aSOI_TERM5_START_HR) { + term = aSOI_TERM4; + } + else if (hour < aSOI_TERM0_START_HR) { + term = aSOI_TERM5; + } + } + + return term; +} + +static int aSOI_ins_chk_live_insect(SET_MANAGER* set_manager, GAME_PLAY* play) { + int live = FALSE; + if (Common_Get(clip.insect_clip)->chk_live_insect_proc != NULL) { + live = (*Common_Get(clip.insect_clip)->chk_live_insect_proc)(set_manager->player_pos.next_bx, set_manager->player_pos.next_bz, (GAME*)play); + } + + return live; +} + +static int aSOI_ins_block_check(SET_MANAGER* set_manager, GAME_PLAY* play) { + int res = FALSE; + if (aSOI_ins_chk_live_insect(set_manager, play) == FALSE) { + u32 block_kind = mFI_BkNum2BlockKind(set_manager->player_pos.next_bx, set_manager->player_pos.next_bz); + + // no insects in the sea acres between town & the island + if ((block_kind & mRF_BLOCKKIND_OFFING) == mRF_BLOCKKIND_OFFING) { + res = TRUE; + } + } + else { + res = TRUE; + } + + return res; +} + +static void aSOI_ins_renewal_time(aSOI_insect_keep_c* keep) { + int term = aSOI_hour_to_term(Common_Get(time.rtc_time.hour)); + keep->now_month = Common_Get(time.rtc_time.month); + keep->now_term = term; +} + +static int aSOI_ins_not_cmp_time(aSOI_insect_keep_c* keep) { + lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time); + int term = aSOI_hour_to_term(rtc_time->hour); + int month = rtc_time->month; + + return (keep->now_month != month || keep->now_term != term); +} + +static void aSOI_ins_renew_term_info(int term) { + Save_Set(insect_term, term); + Save_Set(insect_term_transition_offset, (fqrand() * (f32)(aSOI_TERM_TRANSITION_MAX_DAYS + 1))); +} + +static void aSOI_ins_chk_term_info(int* term0, int* term1, f32* term0_rate) { + static f32 rate[aSOI_TERM_TRANSITION_MAX_DAYS] = { + 5.0f/6.0f, + 4.0f/6.0f, + 3.0f/6.0f, + 2.0f/6.0f, + 1.0f/6.0f + }; + + int now_term; + u32 next_term; + int saved_term; + + saved_term = Save_Get(insect_term); + now_term = Common_Get(time.rtc_time.month) - 1; + next_term = now_term == (lbRTC_DECEMBER - 1) ? 0 : now_term + 1; + + if (ABS(saved_term - now_term) > 1 && saved_term != 0 && now_term != lbRTC_DECEMBER - 1) { + aSOI_ins_renew_term_info(next_term); + *term0 = now_term; + *term1 = now_term; + *term0_rate = 1.0f; + } + else { + lbRTC_time_c next_term_time; + lbRTC_time_c end_term_transition_time; + lbRTC_TimeCopy(&next_term_time, Common_GetPointer(time.rtc_time)); + next_term_time.month = saved_term + 1; + next_term_time.hour = 0; + next_term_time.min = 0; + next_term_time.sec = 0; + + if (saved_term != now_term && now_term == lbRTC_DECEMBER - 1) { + next_term_time.year++; + } + + next_term_time.day = 1; + + lbRTC_Sub_DD(&next_term_time, Save_Get(insect_term_transition_offset)); + lbRTC_TimeCopy(&end_term_transition_time, &next_term_time); + lbRTC_Add_DD(&end_term_transition_time, aSOI_TERM_TRANSITION_MAX_DAYS); + if (lbRTC_IsOverRTC(&end_term_transition_time) == lbRTC_OVER) { + aSOI_ins_renew_term_info(next_term); + *term0 = now_term; + *term1 = now_term; + *term0_rate = 1.0f; + } + else { + if (lbRTC_IsOverRTC(&next_term_time) == lbRTC_OVER) { + int day_interval = lbRTC_GetIntervalDays(&next_term_time, Common_GetPointer(time.rtc_time)); + *term0 = now_term; + *term1 = saved_term; + *term0_rate = rate[day_interval]; + } + else { + *term0 = now_term; + *term1 = now_term; + *term0_rate = 1.0f; + } + } + } +} + +static void aSOI_ins_add_range_info(aSOI_insect_spawn_info_f_c* spawn_info, u8* spawn_info_num) { + static aSOI_insect_spawn_info_f_c additional_data[3] = { + INSECT_SPAWN(ANT, ON_CANDY, 1.0f), + INSECT_SPAWN(ANT, ON_TRASH, 1.0f), + INSECT_SPAWN(COCKROACH, ON_TRASH, 1.0f) + }; + + int i; + + for (i = 0; i < 3; i++) { + bcopy(additional_data + i, spawn_info, sizeof(aSOI_insect_spawn_info_f_c)); + spawn_info++; + } + + (*spawn_info_num) += 3; +} + +static void aSOI_ins_make_insect_normal_range_data(aSOI_insect_keep_c* keep, int month, int term, f32 rate) { + aSOI_term_list_c* month_term_list; + aSOI_term_info_c* month_term_info; + aSOI_insect_spawn_info_f_c* dst_info; + u8 info_num; + int month_info_num; + int i; + + info_num = keep->info_num; + month_term_list = &l_insect_month[month][term]; + month_info_num = month_term_list->count; + month_term_info = month_term_list->term_info; + + dst_info = keep->spawn_info + info_num; + keep->info_num = info_num + month_info_num; + + for (i = 0; i != month_info_num; i++) { + dst_info->type = month_term_info->type; + dst_info->spawn_area = month_term_info->spawn_area; + dst_info->weight = ((f32)month_term_info->weight) * rate; + month_term_info++; + dst_info++; + } +} + +static void aSOI_ins_make_insect_island_range_data(aSOI_insect_keep_c* keep, int term) { + u8 info_num; + aSOI_insect_spawn_info_f_c* dst_info; + aSOI_term_info_c* island_term_info; + aSOI_term_list_c* island_term_list; + int island_info_num; + int i; + + info_num = keep->info_num; + island_term_list = &l_insect_island[term]; + island_info_num = island_term_list->count; + island_term_info = island_term_list->term_info; + + dst_info = keep->spawn_info + info_num; + keep->info_num = info_num + island_info_num; + + for (i = 0; i != island_info_num; i++) { + dst_info->type = island_term_info->type; + dst_info->spawn_area = island_term_info->spawn_area; + dst_info->weight = (f32)island_term_info->weight; + island_term_info++; + dst_info++; + } +} + +static void aSOI_ins_make_hitodama_range_data(aSOI_insect_keep_c* keep) { + aSOI_insect_spawn_info_f_c* dst_info = keep->spawn_info + keep->info_num; + dst_info->type = l_hitodama_time_table.type; + dst_info->spawn_area = l_hitodama_time_table.spawn_area; + dst_info->weight = (f32)l_hitodama_time_table.weight; + keep->info_num = 1; +} + + +static int aSOI_check_hitodama_block_data(int bx, int bz, mEv_gst_hitodama_block_c* hitodama_block_data) { + int i; + int idx; + int res = TRUE; + + for (i = 0, idx = 0; i < 3; i++) { + if (bx == hitodama_block_data->block_x[idx] && bz == hitodama_block_data->block_z[idx]) { + res = FALSE; + break; + } + idx += 2; + } + + return res; +} + +static int aSOI_check_countdown_event(SET_MANAGER* set_manager, mEv_gst_hitodama_block_c* hitodama_block_data) { + int i; + int res = FALSE; + + // Check that the ghost event is active + if (mEv_check_status(mEv_EVENT_GHOST, mEv_STATUS_ACTIVE) == TRUE) { + int n_bx = (u8)set_manager->player_pos.next_bx; + int n_bz = (u8)set_manager->player_pos.next_bz; // idk if this is a fake match or not + int pool_bx; + int pool_bz; + + // Check if the player is transitioning into the lake acre + // NOTE: this only works for the first lake in town, so hacked towns with multiple lakes + // would still spawn spirits in subsequent lake acres. + if (mFI_BlockKind2BkNum(&pool_bx, &pool_bz, mRF_BLOCKKIND_POOL) == TRUE && pool_bx == n_bx && pool_bz == n_bz) { + // Check that each spirit isn't located in the lake acre + for (i = 0; i < mEv_GHOST_HITODAMA_NUM; i++) { + if (pool_bx == hitodama_block_data->block_x[i] && pool_bz == hitodama_block_data->block_z[i]) { + // Spirit is located in the lake acre, re-roll its acre + int t_bx; + int t_bz; + do { + do { + t_bx = 1 + ((int)(fqrand() * (f32)FG_BLOCK_X_NUM)); + t_bz = 1 + ((int)(fqrand() * (f32)FG_BLOCK_Z_NUM)); + } while (t_bx == pool_bx); + } while (t_bz == pool_bz || aSOI_check_hitodama_block_data(t_bx, t_bz, hitodama_block_data) != TRUE); + + hitodama_block_data->block_x[i] = t_bx; + hitodama_block_data->block_z[i] = t_bz; + res = TRUE; + break; + } + } + } + } + + return res; +} + +static int aSOI_check_hitodama_set_block(SET_MANAGER* set_manager, mEv_gst_hitodama_block_c* hitodama_block_data) { + int res = FALSE; + + // Check that spirits are in a valid acre, and if a spirit was removed from the acre + // the player is entering, skip logic. + if (aSOI_check_countdown_event(set_manager, hitodama_block_data) == FALSE) { + u8 next_bx = set_manager->player_pos.next_bx; + u8 next_bz = set_manager->player_pos.next_bz; + int i; + + // Check if any spirit is in the acre the player is transitioning into + for (i = 0; i < mEv_GHOST_HITODAMA_NUM; i++) { + if (next_bx == hitodama_block_data->block_x[i] && + next_bz == hitodama_block_data->block_z[i] + ) { + res = TRUE; + break; + } + } + } + + return res; +} + +static int aSOI_ins_renew_check_range_table(SET_MANAGER* set_manager, aSOI_insect_keep_c* keep) { + static int renew_table[4] = { 0, 1, 2, 3 }; + + u8 spawn_type; + int renew = 0; + u32 block_kind = mFI_BkNum2BlockKind(set_manager->player_pos.next_bx, set_manager->player_pos.next_bz); + + if ((block_kind & mRF_BLOCKKIND_ISLAND) == mRF_BLOCKKIND_ISLAND) { + spawn_type = aSOI_SPAWN_TYPE_ISLAND; + } + else { + mEv_gst_common_c* ghost_common = (mEv_gst_common_c*)mEv_get_common_area(0x72, 0x37); // TODO: definitions for event type, event id + if (ghost_common != NULL && (ghost_common->flags & mEv_GHOST_FLAG_ACTIVE) != 0 && + aSOI_check_hitodama_set_block(set_manager, &ghost_common->hitodama_block_data) == TRUE + ) { + spawn_type = aSOI_SPAWN_TYPE_SPIRIT; + } + else { + spawn_type = aSOI_SPAWN_TYPE_TOWN; + } + } + + if (keep->spawn_type != spawn_type) { + keep->spawn_type = spawn_type; + renew = renew_table[spawn_type]; + } + else { + if (spawn_type != aSOI_SPAWN_TYPE_SPIRIT && aSOI_ins_not_cmp_time(keep) == TRUE) { + renew = renew_table[spawn_type]; + } + } + + return renew; +} + +static void aSOI_ins_make_range_data(SET_MANAGER* set_manager) { + aSOI_insect_keep_c* keep = &set_manager->keep.insect_keep; + int day_term; + + switch (aSOI_ins_renew_check_range_table(set_manager, keep)) { + case aSOI_SPAWN_TYPE_TOWN: + { + int term0, term1; + f32 term0_rate; + day_term = aSOI_hour_to_term(Common_Get(time.rtc_time.hour)); + aSOI_ins_chk_term_info(&term0, &term1, &term0_rate); + + bzero(keep->spawn_info, 0x158); + keep->info_num = 0; + aSOI_ins_make_insect_normal_range_data(keep, term0, day_term, term0_rate); + + if (term0_rate != 1.0f) { + aSOI_ins_make_insect_normal_range_data(keep, term1, day_term, 1.0f - term0_rate); + } + + aSOI_ins_add_range_info(keep->spawn_info + keep->info_num, &keep->info_num); + aSOI_ins_renewal_time(keep); + break; + } + + case aSOI_SPAWN_TYPE_ISLAND: + { + day_term = aSOI_hour_to_term(Common_Get(time.rtc_time.hour)); + + bzero(keep->spawn_info, 0x158); // not sure where the 0x158 comes from + keep->info_num = 0; + + aSOI_ins_make_insect_island_range_data(keep, day_term); + aSOI_ins_add_range_info(keep->spawn_info + keep->info_num, &keep->info_num); + aSOI_ins_renewal_time(keep); + break; + } + + case aSOI_SPAWN_TYPE_SPIRIT: + { + bzero(keep->spawn_info, 0x158); + keep->info_num = 0; + + aSOI_ins_make_hitodama_range_data(keep); + break; + } + } +} + +static int aSOI_ins_field_fg_check_get(mActor_name_t* fg_items, u16* fg_deposit, mActor_name_t min_item_no, mActor_name_t max_item_no) { + int spawn_found = FALSE; + + if (fg_items != NULL && fg_deposit != NULL) { + int ut_z; + for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) { + int ut_x; + for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) { + if (ut_z >= 2 && ut_z < UT_Z_NUM - 2 && + ut_x >= 2 && ut_x < UT_X_NUM - 2 && + min_item_no <= *fg_items && *fg_items <= max_item_no && + mFI_GetLineDeposit(fg_deposit, ut_x) == FALSE + ) { + spawn_found = TRUE; + break; + } + + fg_items++; + } + + fg_deposit++; + if (spawn_found == TRUE) { + break; + } + } + } + + return spawn_found; +} + +static int aSOI_ins_field_attr_check_get_sub(mCoBG_Collision_u* collision_data, int spawn_area) { + int valid = FALSE; + u32 attribute = collision_data->data.unit_attribute; + + switch (spawn_area) { + case aSOI_SPAWN_AREA_ON_GROUND: + { + // valid on: grass, most soil type, bush + if (attribute <= mCoBG_ATTRIBUTE_SOIL1 || attribute == mCoBG_ATTRIBUTE_BUSH) { + valid = TRUE; + } + + break; + } + + case aSOI_SPAWN_AREA_IN_BUSH: + { + if (attribute == mCoBG_ATTRIBUTE_BUSH) { + valid = TRUE; + } + + break; + } + + case aSOI_SPAWN_AREA_FLYING_NEAR_WATER: + { + if (mCoBG_CheckWaterAttribute(attribute) == TRUE) { + valid = TRUE; + } + + break; + } + + case aSOI_SPAWN_AREA_ON_WATER: + { + if (attribute >= mCoBG_ATTRIBUTE_WATER && attribute <= mCoBG_ATTRIBUTE_RIVER_NE) { + valid = TRUE; + } + + break; + } + } + + return valid; +} + +static int aSOI_ins_field_attr_check_get(mCoBG_Collision_u* collision_data, int spawn_area) { + int res = FALSE; + + if (collision_data != NULL) { + int ut_z; + + for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) { + int ut_x; + + for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) { + if (ut_z >= 2 && ut_z < UT_Z_NUM - 2 && ut_x >= 2 && ut_x < UT_X_NUM - 2) { + res = aSOI_ins_field_attr_check_get_sub(collision_data, spawn_area); + } + + if (res == TRUE) { + break; + } + + collision_data++; + } + + if (res == TRUE) { + break; + } + } + } + + return res; +} + +#define aSOI_tree_check(fg_item) ( \ + (fg_item) == TREE || \ + (fg_item) == TREE_FTR || \ + (fg_item) == TREE_LIGHTS || \ + (fg_item) == TREE_BELLS || \ + (fg_item) == TREE_APPLE_FRUIT || \ + (fg_item) == TREE_ORANGE_FRUIT || \ + (fg_item) == TREE_PEACH_FRUIT || \ + (fg_item) == TREE_PEAR_FRUIT || \ + (fg_item) == TREE_CHERRY_FRUIT || \ + (fg_item) == TREE_1000BELLS || \ + (fg_item) == TREE_10000BELLS || \ + (fg_item) == TREE_30000BELLS || \ + (fg_item) == TREE_100BELLS || \ + (fg_item) == CEDAR_TREE || \ + (fg_item) == CEDAR_TREE_BELLS || \ + (fg_item) == CEDAR_TREE_FTR || \ + (fg_item) == CEDAR_TREE_LIGHTS || \ + (fg_item) == GOLD_TREE || \ + (fg_item) == GOLD_TREE_BELLS || \ + (fg_item) == GOLD_TREE_FTR || \ + (fg_item) == GOLD_TREE_SHOVEL \ +) + +static int aSOI_ins_field_tree_check_get(mActor_name_t* fg_item) { + int valid = FALSE; + + if (fg_item != NULL) { + int ut_z; + + for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) { + int ut_x; + for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) { + if (ut_z >= 2 && ut_z < UT_Z_NUM - 2 && ut_x >= 2 && ut_x < UT_X_NUM - 2 && aSOI_tree_check(*fg_item)) { + valid = TRUE; + break; + } + fg_item++; + } + + if (valid == TRUE) { + break; + } + } + } + + return valid; +} + +static int aSOI_ins_field_attr_and_fg_check_get_sub(mCoBG_Collision_u* collision_data, mActor_name_t* fg_item, int spawn_area) { + int valid = FALSE; + u32 attribute = collision_data->data.unit_attribute; + + switch (spawn_area) { + case aSOI_SPAWN_AREA_UNDERGROUND: + { + if (mCoBG_CheckHole_OrgAttr(attribute) == TRUE && *fg_item == EMPTY_NO) { + valid = TRUE; + } + break; + } + } + + return valid; +} + +static int aSOI_ins_field_attr_and_fg_check_get(mCoBG_Collision_u* collision_data, mActor_name_t* fg_item, int spawn_area) { + int res = FALSE; + + if (collision_data != NULL && fg_item != NULL) { + int ut_z; + for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) { + int ut_x; + for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) { + if (ut_z >= 2 && ut_z < UT_Z_NUM - 2 && ut_x >= 2 && ut_x < UT_X_NUM - 2) { + res = aSOI_ins_field_attr_and_fg_check_get_sub(collision_data, fg_item, spawn_area); + } + + if (res == TRUE) { + break; + } + + collision_data++; + fg_item++; + } + + if (res == TRUE) { + break; + } + } + } + + return res; +} + +typedef int (*aSOI_chk_live_area_proc)(aSOI_insect_spawn_info_f_c*, int, mActor_name_t*, u16*, mActor_name_t, mActor_name_t, mCoBG_Collision_u*, aSetMgr_player_pos_c*, int); + +typedef struct insect_check_s { + mActor_name_t min_item_no; + mActor_name_t max_item_no; + aSOI_chk_live_area_proc chk_live_area_proc; + int spawn_category; +} aSOI_chk_live_area_data_c; + +static void aSOI_ins_change_how_to_make(aSOI_insect_spawn_info_f_c* spawn_info, int info_num, u8 new_spawn_area, u8 target_spawn_area) { + int i; + + for (i = 0; i < info_num; i++) { + if (target_spawn_area == spawn_info[i].spawn_area) { + spawn_info[i].spawn_area = new_spawn_area; + } + } +} + +static void aSOI_ins_clear_prob(aSOI_insect_spawn_info_f_c* spawn_info, int info_num, int target_spawn_area) { + int i; + + for (i = 0; i < info_num; i++) { + if (target_spawn_area == spawn_info->spawn_area) { + spawn_info->weight = 0.0f; + } + spawn_info++; + } +} + +static void aSOI_ins_limit_insect_data(aSOI_insect_spawn_info_f_c* spawn_info, int info_num, int on_candy, int on_trash) { + int i; + + for (i = 0; i < info_num; i++) { + switch (spawn_info->spawn_area) { + case aSOI_SPAWN_AREA_ON_CANDY: + { + if (on_candy == FALSE) { + spawn_info->weight = 0.0f; + } + break; + } + + case aSOI_SPAWN_AREA_ON_TRASH: + { + if (on_trash == FALSE) { + spawn_info->weight = 0.0f; + } + break; + } + + default: + { + spawn_info->weight = 0.0f; + break; + } + } + spawn_info++; + } +} + +static int aSOI_ins_get_idx(aSOI_insect_spawn_info_f_c* spawn_info, int info_num, int spawn_on_candy_or_trash) { + static f32 env_rate_table[mFAs_FIELDRANK_NUM] = { + 0.500f, + 0.750f, + 0.875f, + 1.000f, + 1.000f, + 1.000f, + 1.000f + }; + + f32 total_weight = 0.0f; + f32 env_rate; + f32 selected_weight; + int selected = aSOI_INSECT_TYPE_INVALID; + int i; + int rank; + aSOI_insect_spawn_info_f_c* spawn_info_p = spawn_info; + + for (i = 0; i < info_num; i++) { + total_weight += spawn_info_p->weight; + spawn_info_p++; + } + + if (total_weight > 0.0f) { + if (spawn_on_candy_or_trash == FALSE) { + rank = mFAs_GetFieldRank(); + + if (total_weight > 100.0f) { + selected_weight = fqrand() * total_weight; + } + else { + selected_weight = fqrand() * 100.0f; // chance to not spawn bug here if below 100.0f total weight + } + + if (rank < mFAs_FIELDRANK_ZERO || rank > mFAs_FIELDRANK_SIX) { + if (rank < mFAs_FIELDRANK_ZERO) { + rank = mFAs_FIELDRANK_ZERO; + } + + if (rank > mFAs_FIELDRANK_SIX) { + rank = mFAs_FIELDRANK_SIX; + } + } + + env_rate = env_rate_table[rank]; + } + else { + env_rate = 1.0f; + selected_weight = fqrand() * total_weight; + } + + for (i = 0; i < info_num; i++) { + selected_weight -= spawn_info->weight * env_rate; + if (selected_weight < 0.0f) { + selected = i; + break; + } + spawn_info++; + } + } + + return selected; +} + +static void aSOI_ins_set_insect_data(aSOI_set_data_c* set_data, int type, aSetMgr_player_pos_c* player_pos) { + if (type != aSOI_INSECT_TYPE_INVALID) { + int live_ut_x; + int live_ut_z; + + if (aSOI_get_live_ut(set_data, &live_ut_x, &live_ut_z) == TRUE) { + mActor_name_t item; + + set_data->type = type; + set_data->ut_x = live_ut_x; + set_data->ut_z = live_ut_z; + set_data->should_spawn = TRUE; + set_data->extra_data = 0; + + if (type == aSOI_INSECT_TYPE_COCKROACH && mFI_GetBlockUtNum2FG(&item, player_pos->next_bx, player_pos->next_bz, live_ut_x, live_ut_z) == TRUE) { + if (aSOI_tree_check(item)) { + set_data->extra_data = 4; // TODO: definition (*_ON_TREE) + } + else if (item == 0x2F03) { + set_data->extra_data = 6; // TODO: definition (*_ON_SPOILED_KABU) + } + } + } + else { + set_data->should_spawn = FALSE; + } + } +} + +static int aSOI_ins_chk_live_area_type_free( + aSOI_insect_spawn_info_f_c* spawn_info, int info_num, + mActor_name_t* fg_item, u16* fg_deposit, + mActor_name_t min_item_no, mActor_name_t max_item_no, + mCoBG_Collision_u* collision_data, + aSetMgr_player_pos_c* player_pos, + int spawn_area +) { + return aSOI_ins_field_fg_check_get(fg_item, fg_deposit, min_item_no, max_item_no); +} + +static int aSOI_ins_chk_live_area_type_tree( + aSOI_insect_spawn_info_f_c* spawn_info, int info_num, + mActor_name_t* fg_item, u16* fg_deposit, + mActor_name_t min_item_no, mActor_name_t max_item_no, + mCoBG_Collision_u* collision_data, + aSetMgr_player_pos_c* player_pos, + int spawn_area +) { + return aSOI_ins_field_tree_check_get(fg_item); +} + +static int aSOI_ins_chk_live_area_type_free_without_rain_and_snow( + aSOI_insect_spawn_info_f_c* spawn_info, int info_num, + mActor_name_t* fg_item, u16* fg_deposit, + mActor_name_t min_item_no, mActor_name_t max_item_no, + mCoBG_Collision_u* collision_data, + aSetMgr_player_pos_c* player_pos, + int spawn_area +) { + int res = FALSE; + + if (Common_Get(weather) != mEnv_WEATHER_RAIN && Common_Get(weather) != mEnv_WEATHER_SNOW) { + res = aSOI_ins_field_fg_check_get(fg_item, fg_deposit, min_item_no, max_item_no); + } + + return res; +} + +static int aSOI_ins_chk_live_area_type_flower( + aSOI_insect_spawn_info_f_c* spawn_info, int info_num, + mActor_name_t* fg_item, u16* fg_deposit, + mActor_name_t min_item_no, mActor_name_t max_item_no, + mCoBG_Collision_u* collision_data, + aSetMgr_player_pos_c* player_pos, + int spawn_area +) { + int res = FALSE; + + if (Common_Get(weather) != mEnv_WEATHER_RAIN) { + res = aSOI_ins_field_fg_check_get(fg_item, fg_deposit, min_item_no, max_item_no); + } + + return res; +} + +static int aSOI_ins_chk_live_area_type_flower_or_free( + aSOI_insect_spawn_info_f_c* spawn_info, int info_num, + mActor_name_t* fg_item, u16* fg_deposit, + mActor_name_t min_item_no, mActor_name_t max_item_no, + mCoBG_Collision_u* collision_data, + aSetMgr_player_pos_c* player_pos, + int spawn_area +) { + int res = FALSE; + + if (Common_Get(weather) != mEnv_WEATHER_RAIN) { + u8 area; + res = aSOI_ins_field_fg_check_get(fg_item, fg_deposit, min_item_no, max_item_no); + /* prefer flowers, but if unable to spawn like that, revert to flying around */ + area = aSOI_SPAWN_AREA_ON_FLOWER; + if (!res) { + area = aSOI_SPAWN_AREA_FLYING; + } + aSOI_ins_change_how_to_make(spawn_info, info_num, area, aSOI_SPAWN_AREA_FLYING_NEAR_FLOWERS_OR_AROUND); + } + + return res; +} + +static int aSOI_ins_chk_live_area_type_flower_rain( + aSOI_insect_spawn_info_f_c* spawn_info, int info_num, + mActor_name_t* fg_item, u16* fg_deposit, + mActor_name_t min_item_no, mActor_name_t max_item_no, + mCoBG_Collision_u* collision_data, + aSetMgr_player_pos_c* player_pos, + int spawn_area +) { + int res = FALSE; + + if (Common_Get(weather) == mEnv_WEATHER_RAIN) { + res = aSOI_ins_field_fg_check_get(fg_item, fg_deposit, min_item_no, max_item_no); + } + + return res; +} + +static int aSOI_ins_chk_live_area_type_pond( + aSOI_insect_spawn_info_f_c* spawn_info, int info_num, + mActor_name_t* fg_item, u16* fg_deposit, + mActor_name_t min_item_no, mActor_name_t max_item_no, + mCoBG_Collision_u* collision_data, + aSetMgr_player_pos_c* player_pos, + int spawn_area +) { + int res = FALSE; + u32 block_kind = mFI_BkNum2BlockKind(player_pos->next_bx, player_pos->next_bz); + + if ((block_kind & mRF_BLOCKKIND_POOL) == mRF_BLOCKKIND_POOL || + ((block_kind & mRF_BLOCKKIND_WATERFALL) != mRF_BLOCKKIND_WATERFALL && + (block_kind & mRF_BLOCKKIND_RIVER) != mRF_BLOCKKIND_RIVER && + (block_kind & mRF_BLOCKKIND_MARINE) != mRF_BLOCKKIND_MARINE) + ) { + res = aSOI_ins_field_attr_check_get(collision_data, spawn_area); + } + + return res; +} + +static int aSOI_ins_chk_live_area_type_other( + aSOI_insect_spawn_info_f_c* spawn_info, int info_num, + mActor_name_t* fg_item, u16* fg_deposit, + mActor_name_t min_item_no, mActor_name_t max_item_no, + mCoBG_Collision_u* collision_data, + aSetMgr_player_pos_c* player_pos, + int spawn_area +) { + return aSOI_ins_field_attr_check_get(collision_data, spawn_area); +} + +static int aSOI_ins_chk_live_area_type_dig_hole( + aSOI_insect_spawn_info_f_c* spawn_info, int info_num, + mActor_name_t* fg_item, u16* fg_deposit, + mActor_name_t min_item_no, mActor_name_t max_item_no, + mCoBG_Collision_u* collision_data, + aSetMgr_player_pos_c* player_pos, + int spawn_area +) { + return aSOI_ins_field_attr_and_fg_check_get(collision_data, fg_item, spawn_area); +} + +static int aSOI_ins_chk_live_area_type_nothing( + aSOI_insect_spawn_info_f_c* spawn_info, int info_num, + mActor_name_t* fg_item, u16* fg_deposit, + mActor_name_t min_item_no, mActor_name_t max_item_no, + mCoBG_Collision_u* collision_data, + aSetMgr_player_pos_c* player_pos, + int spawn_area +) { + return TRUE; +} + +#define aSOI_make_chk_live_data(min_item_no, max_item_no, func, cat) { (min_item_no), (max_item_no), func, aSOI_SPAWN_CATEGORY_##cat } +static aSOI_chk_live_area_data_c aSOI_chk_live_area_data[aSOI_SPAWN_AREA_NUM] = { + aSOI_make_chk_live_data(TREE, TREE, &aSOI_ins_chk_live_area_type_tree, TREE), /* aSOI_SPAWN_AREA_ON_TREE */ + aSOI_make_chk_live_data(FLOWER_PANSIES0, FLOWER_COSMOS2, &aSOI_ins_chk_live_area_type_flower, FG_ITEM_RANGE), /* aSOI_SPAWN_AREA_ON_FLOWER */ + aSOI_make_chk_live_data(FLOWER_PANSIES0, FLOWER_COSMOS2, &aSOI_ins_chk_live_area_type_flower_rain, FG_ITEM_RANGE), /* aSOI_SPAWN_AREA_RAINING_ON_FLOWER */ + aSOI_make_chk_live_data(EMPTY_NO, EMPTY_NO, &aSOI_ins_chk_live_area_type_free, FG_ITEM_RANGE), /* aSOI_SPAWN_AREA_FLYING */ + aSOI_make_chk_live_data(EMPTY_NO, EMPTY_NO, &aSOI_ins_chk_live_area_type_other, UT_ATTRIBUTE), /* aSOI_SPAWN_AREA_ON_GROUND */ + aSOI_make_chk_live_data(EMPTY_NO, EMPTY_NO, &aSOI_ins_chk_live_area_type_other, UT_ATTRIBUTE), /* aSOI_SPAWN_AREA_IN_BUSH */ + aSOI_make_chk_live_data(EMPTY_NO, EMPTY_NO, &aSOI_ins_chk_live_area_type_other, UT_ATTRIBUTE), /* aSOI_SPAWN_AREA_FLYING_NEAR_WATER */ + aSOI_make_chk_live_data(EMPTY_NO, EMPTY_NO, &aSOI_ins_chk_live_area_type_pond, UT_ATTRIBUTE), /* aSOI_SPAWN_AREA_ON_WATER */ + aSOI_make_chk_live_data(ITM_FOOD_CANDY, ITM_FOOD_CANDY, &aSOI_ins_chk_live_area_type_free_without_rain_and_snow, FG_ITEM_RANGE), /* aSOI_SPAWN_AREA_ON_CANDY */ + aSOI_make_chk_live_data(ITM_KABU_SPOILED, ITM_KABU_SPOILED, &aSOI_ins_chk_live_area_type_free_without_rain_and_snow, FG_ITEM_RANGE), /* aSOI_SPAWN_AREA_ON_TRASH */ + aSOI_make_chk_live_data(ROCK_A, ROCK_E, &aSOI_ins_chk_live_area_type_free, FG_ITEM_RANGE), /* aSOI_SPAWN_AREA_UNDER_ROCK */ + aSOI_make_chk_live_data(EMPTY_NO, EMPTY_NO, &aSOI_ins_chk_live_area_type_dig_hole, UT_ATTRIBUTE_AND_FG_ITEM_RANGE), /* aSOI_SPAWN_AREA_UNDERGROUND */ + aSOI_make_chk_live_data(FLOWER_PANSIES0, FLOWER_COSMOS2, &aSOI_ins_chk_live_area_type_flower_or_free, FG_ITEM_RANGE), /* aSOI_SPAWN_AREA_FLYING_NEAR_FLOWERS_OR_AROUND */ + aSOI_make_chk_live_data(EMPTY_NO, EMPTY_NO, &aSOI_ins_chk_live_area_type_nothing, FG_ITEM_RANGE) /* aSOI_SPAWN_AREA_NOTHING */ +}; + +static void aSOI_make_live_ut(aSOI_set_data_c* set_data, int spawn_area, mActor_name_t* fg_item, mCoBG_Collision_u* collision_data) { + // Start pointers at the second row of units + aSOI_chk_live_area_data_c* chk_live_area_data = aSOI_chk_live_area_data + spawn_area; + + mActor_name_t min_item = chk_live_area_data->min_item_no; + mActor_name_t max_item = chk_live_area_data->max_item_no; + + int ut_z; + int ut_x; + mActor_name_t* fg_item_p = fg_item + 2 * UT_X_NUM; + mCoBG_Collision_u* collision_data_p = collision_data + 2 * UT_X_NUM; + + for (ut_z = 2; ut_z < UT_Z_NUM - 2; ut_z++) { + for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) { + if (ut_z >= 2 && ut_z < UT_Z_NUM - 2 && ut_x >= 2 && ut_x < UT_X_NUM - 2) { + switch (chk_live_area_data->spawn_category) { + case aSOI_SPAWN_CATEGORY_FG_ITEM_RANGE: + { + if (min_item <= *fg_item_p && *fg_item_p <= max_item) { + aSOI_set_live_ut(set_data, ut_x, ut_z, TRUE); + } + break; + } + + case aSOI_SPAWN_CATEGORY_UT_ATTRIBUTE: + { + if (aSOI_ins_field_attr_check_get_sub(collision_data_p, spawn_area) == TRUE) { + aSOI_set_live_ut(set_data, ut_x, ut_z, TRUE); + } + break; + } + + case aSOI_SPAWN_CATEGORY_TREE: + { + if (aSOI_tree_check(*fg_item_p)) { + aSOI_set_live_ut(set_data, ut_x, ut_z, TRUE); + } + break; + } + + case aSOI_SPAWN_CATEGORY_UT_ATTRIBUTE_AND_FG_ITEM_RANGE: + { + if (aSOI_ins_field_attr_and_fg_check_get_sub(collision_data_p, fg_item_p, spawn_area) == TRUE) { + aSOI_set_live_ut(set_data, ut_x, ut_z, TRUE); + } + break; + } + } + } + + fg_item_p++; + collision_data_p++; + } + } +} + +static void aSOI_ins_decide_insect(aSOI_set_data_c* set_data, aSetMgr_player_pos_c* player_pos, aSOI_insect_spawn_info_f_c* spawn_info, int info_num) { + mActor_name_t* fg_item; + u16* deposit; + mCoBG_Collision_u* collision_data; + int spawn_idx; + int i; + int candy_spawn; + int trash_spawn; + + candy_spawn = FALSE; + trash_spawn = FALSE; + fg_item = mFI_BkNumtoUtFGTop(player_pos->next_bx, player_pos->next_bz); + deposit = mFI_GetDepositP(player_pos->next_bx, player_pos->next_bz); + collision_data = mFI_GetBkNum2ColTop(player_pos->next_bx, player_pos->next_bz); + + for (i = aSOI_SPAWN_AREA_ON_TREE; i < aSOI_SPAWN_AREA_NUM; i++) { + // Call chk_live_area proc to see if an insect with this spawn area can spawn in the acre + int can_spawn = (*aSOI_chk_live_area_data[i].chk_live_area_proc)( + spawn_info, info_num, + fg_item, deposit, + aSOI_chk_live_area_data[i].min_item_no, aSOI_chk_live_area_data[i].max_item_no, + collision_data, + player_pos, + i + ); + + if (can_spawn == TRUE) { + switch(i) { + case aSOI_SPAWN_AREA_ON_CANDY: + { + candy_spawn = TRUE; + break; + } + + case aSOI_SPAWN_AREA_ON_TRASH: + { + trash_spawn = TRUE; + break; + } + } + } + // If no spawns are available, remove any insect weight for this spawn type from the spawn list + if (can_spawn == FALSE) { + aSOI_ins_clear_prob(spawn_info, info_num, i); + } + } + + // If a candy spawn or trash spawn (spoiled turnip) is available, remove all other weights + if (candy_spawn == TRUE || trash_spawn == TRUE) { + aSOI_ins_limit_insect_data(spawn_info, info_num, candy_spawn, trash_spawn); + } + + spawn_idx = aSOI_ins_get_idx(spawn_info, info_num, candy_spawn | trash_spawn); + if (spawn_idx != aSOI_INSECT_TYPE_INVALID) { + aSOI_insect_spawn_info_f_c* info = spawn_info + spawn_idx; + int spawn_area = info->spawn_area; + + // Check that the spawn area is an actual valid spawn area + if (spawn_area < aSOI_SPAWN_AREA_FLYING_NEAR_FLOWERS_OR_AROUND) { + aSOI_make_live_ut(set_data, spawn_area, fg_item, collision_data); + aSOI_ins_set_insect_data(set_data, info->type, player_pos); + } + } +} + +static int aSOI_ins_make_sub(aSOI_set_data_c* set_data, aSetMgr_player_pos_c* player_pos, GAME* game) { + aINS_Init_c insect_init; + xyz_t wpos; + int res = FALSE; + + if (set_data->should_spawn == TRUE) { + mFI_BkandUtNum2Wpos(&wpos, player_pos->next_bx, player_pos->next_bz, set_data->ut_x, set_data->ut_z); + insect_init.insect_type = set_data->type; + wpos.x += mFI_UT_WORLDSIZE_X_F / 2.0f; + wpos.z += mFI_UT_WORLDSIZE_Z_F / 2.0f; + + insect_init.position = wpos; + insect_init.extra_data = set_data->extra_data; + insect_init.game = game; + + if (insect_init.insect_type == aSOI_INSECT_TYPE_ANT) { + (*Common_Get(clip).insect_clip->make_ant_proc)(&insect_init, player_pos->next_bx, player_pos->next_bz); + res = TRUE; + } + else { + if ((*Common_Get(clip).insect_clip->make_insect_proc)(&insect_init, FALSE)) { + res = TRUE; + } + } + set_data->should_spawn = FALSE; + } + + return res; +} + +static int aSOI_ins_make(aSOI_set_data_c* set_data, aSetMgr_player_pos_c* player_pos, GAME* game) { + int res = FALSE; + + if (set_data->should_spawn == TRUE && Common_Get(clip).insect_clip->make_insect_proc != NULL && Common_Get(clip).insect_clip->make_ant_proc != NULL) { + aSOI_insect_birth_sum_c* birth_sum = l_insect_birth_sum + set_data->type; + int birth_num = birth_sum->min_birth_count + (int)(fqrand() * (f32)birth_sum->additional_range); + + while (birth_num != 0) { + res = aSOI_ins_make_sub(set_data, player_pos, game); + if (res == FALSE) { + break; + } + + birth_num--; + if (birth_num > 0) { + aSOI_ins_set_insect_data(set_data, set_data->type, player_pos); + } + } + } + + return res; +} + +extern int aSOI_insect_set(SET_MANAGER* set_manager, GAME_PLAY* play) { + static aSOI_insect_spawn_info_f_c copy_range[aSetMgr_INSECT_SPAWN_INFO_COUNT]; + static aSOI_set_data_c set_data; + + aSOI_insect_keep_c* keep = &set_manager->keep.insect_keep; + int res = FALSE; + + if (aSOI_ins_block_check(set_manager, play) == FALSE) { + aSOI_ins_clear_set_data(&set_data); + aSOI_ins_make_range_data(set_manager); + + if (keep->info_num > 0) { + int i; + + // No clue why they didn't do bcopy(set_manager->keep.insect_keep.spawn_info, copy_range, aSetMgr_INSECT_SPAWN_INFO_COUNT * sizeof(aSOI_insect_spawn_info_f_c)); + for (i = 0; i < aSetMgr_INSECT_SPAWN_INFO_COUNT; i++) { + bcopy(keep->spawn_info + i, copy_range + i, sizeof(aSOI_insect_spawn_info_f_c)); + } + + aSOI_ins_decide_insect(&set_data, &set_manager->player_pos, copy_range, keep->info_num); + res = aSOI_ins_make(&set_data, &set_manager->player_pos, (GAME*)play); + } + } + + return res; +}