diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 92e1e980..4ec4c2b3 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -774,6 +774,10 @@ ac_ins_amenbo.c: .text: [0x80595C74, 0x80596388] .rodata: [0x80649E70, 0x80649EC8] .data: [0x806C3200, 0x806C3230] +ac_ins_batta.c: + .text: [0x80596388, 0x80597708] + .rodata: [0x80649EC8, 0x80649F60] + .data: [0x806C3230, 0x806C32B8] ac_ins_goki.c: .text: [0x80599A2C, 0x8059A8E8] .rodata: [0x8064A028, 0x8064A090] diff --git a/include/ac_ins_batta.h b/include/ac_ins_batta.h new file mode 100644 index 00000000..3a28d42e --- /dev/null +++ b/include/ac_ins_batta.h @@ -0,0 +1,17 @@ +#ifndef AC_INS_BATTA_H +#define AC_INS_BATTA_H + +#include "types.h" +#include "ac_insect_h.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern void aIBT_actor_init(ACTOR* actor, GAME* game); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/ac_ins_batta.c b/src/ac_ins_batta.c new file mode 100644 index 00000000..1194c768 --- /dev/null +++ b/src/ac_ins_batta.c @@ -0,0 +1,594 @@ +#include "ac_ins_batta.h" + +#include "m_field_info.h" +#include "m_name_table.h" +#include "m_common_data.h" +#include "m_player_lib.h" +#include "ac_set_ovl_insect.h" + +enum { + aIBT_ACTION_AVOID, + aIBT_ACTION_LET_ESCAPE, + aIBT_ACTION_CHANGE_DIRECTION, + aIBT_ACTION_WAIT, + aIBT_ACTION_JUMP, + aIBT_ACTION_IN_WATER, + + aIBT_ACTION_NUM +}; + +static int aIBT_check_live_condition(aINS_INSECT_ACTOR*); +static void aIBT_actor_move(ACTOR*,GAME*); +static void aIBT_actor_first_move(ACTOR*,GAME*); +static void aIBT_setupAction(aINS_INSECT_ACTOR*,int, GAME*); + + +extern void aIBT_actor_init(ACTOR* actor, GAME* game) { + PLAYER_ACTOR* player; + aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actor; + + actor->gravity = 0.2f; + actor->max_velocity_y = -20.0f; + + insect->bg_type = 2; + switch (insect->type) { + case aSOI_INSECT_TYPE_LONG_LOCUST: + insect->item = ITM_INSECT13; + break; + case aSOI_INSECT_TYPE_MIGRATORY_LOCUST: + insect->item = ITM_INSECT14; + break; + case aSOI_INSECT_TYPE_CRICKET: + insect->item = ITM_INSECT15; + break; + case aSOI_INSECT_TYPE_GRASSHOPPER: + insect->item = ITM_INSECT16; + break; + case aSOI_INSECT_TYPE_BELL_CRICKET: + insect->item = ITM_INSECT17; + break; + case aSOI_INSECT_TYPE_PINE_CRICKET: + insect->item = ITM_INSECT18; + break; + } + insect->insect_flags.bit_4 = FALSE; + + if (actor->actor_specific == 0) { + if (aIBT_check_live_condition(insect) == TRUE) { + actor->world.position.y = mCoBG_GetBgY_OnlyCenter_FromWpos(actor->world.position, 0.0f); + actor->mv_proc = aIBT_actor_first_move; + mFI_BkNum2WposXZ(&insect->f32_work2, &insect->f32_work3, actor->block_x, actor->block_z); + insect->f32_work2 += 320.0f; + insect->f32_work3 += 320.0f; + aIBT_setupAction(insect, aIBT_ACTION_CHANGE_DIRECTION, game); + } + } else { + GAME_PLAY* play = (GAME_PLAY*)game; + player = GET_PLAYER_ACTOR(play); + if (player != NULL) { + actor->world.position.y = 40.0f + player->actor_class.world.position.y; + } + actor->mv_proc = aIBT_actor_move; + aIBT_setupAction(insect, aIBT_ACTION_LET_ESCAPE, game); + } +} + +static int aIBT_check_live_condition(aINS_INSECT_ACTOR* insect) { + int cond; + + cond = TRUE; + if (mCoBG_ExistHeightGap_KeepAndNow(insect->tools_actor.actor_class.world.position) == TRUE) { + cond = FALSE; + } else if (Common_Get(weather) == mEnv_WEATHER_RAIN) { + cond = FALSE; + } else { + mActor_name_t* item; + item = mFI_GetUnitFG(insect->tools_actor.actor_class.world.position); + if ((item == NULL) || (*item == RSV_NO)) { + cond = FALSE; + } else if ((*item >= HOLE_START) && (*item <= HOLE_END)) { + cond = FALSE; + } else { + switch ((*item >> 0xC) & 0xF) { + case 4: + break; + case 1: + case 2: + case 3: + case 5: + cond = FALSE; + break; + } + } + } + if (cond == FALSE) { + insect->insect_flags.destruct = TRUE; + } + return cond; +} + +static void aIBT_anime_proc(aINS_INSECT_ACTOR* insect) { + switch (insect->type) { + case aSOI_INSECT_TYPE_BELL_CRICKET: + insect->_1E0 += 1.0f; + break; + default: + insect->_1E0 += 0.3f; + break; + } + + if (insect->_1E0 >= 2.0f) { + insect->_1E0 -= 2.0f; + } +} + +static int aIBT_check_ball(aINS_INSECT_ACTOR* insect) { + f32 x, z; + int ret = 0; + + x = Common_Get(ball_pos).x - insect->tools_actor.actor_class.world.position.x; + z = Common_Get(ball_pos).z - insect->tools_actor.actor_class.world.position.z; + if (((x * x) + (z * z)) < 3600.0f) { + ret = 1; + } + return ret; +} + +static void aIBT_set_fly_se(aINS_INSECT_ACTOR* insect) { + switch (insect->type) { + case aSOI_INSECT_TYPE_LONG_LOCUST: + sAdo_OngenPos((u32)insect, 0xA2, &insect->tools_actor.actor_class.world.position); + break; + case aSOI_INSECT_TYPE_MIGRATORY_LOCUST: + sAdo_OngenPos((u32)insect, 0xA3, &insect->tools_actor.actor_class.world.position); + break; + } +} + +static int aIBT_check_player_net_sub(xyz_t* net_pos, aINS_INSECT_ACTOR* insect) { + int ret; + u32 label; + + ret = FALSE; + if (mPlib_Check_StopNet(net_pos) == TRUE) { + u32 label = mPlib_Get_item_net_catch_label(); + if (label == (u32)insect) { + ret = TRUE; + } + } + return ret; +} + +static int aIBT_check_player_net(aINS_INSECT_ACTOR* insect) { + xyz_t arg; + int ret; + + ret = FALSE; + if (insect->s32_work1 == 0) { + if (aIBT_check_player_net_sub(&arg, insect) == TRUE) { + ret = TRUE; + insect->s32_work1 = 1; + } else { + aIBT_set_fly_se(insect); + } + } else { + ret = TRUE; + } + return ret; +} + +static int aIBT_check_player_net2(aINS_INSECT_ACTOR* insect) { + xyz_t pos; + f32 x, z; + int ret; + + ret = FALSE; + if (mPlib_Check_StopNet(&pos) == TRUE) { + u32 label = mPlib_Get_item_net_catch_label(); + if (label == (u32)insect) { + insect->s32_work1 = 1; + } else { + x = pos.x - insect->tools_actor.actor_class.world.position.x; + z = pos.z - insect->tools_actor.actor_class.world.position.z; + if (((x * x) + (z * z)) < 4900.0f) { + ret = TRUE; + } + } + } + return ret; +} + +static int aIBT_check_player_scoop(aINS_INSECT_ACTOR* insect) { + xyz_t pos; + f32 x, z; + int ret; + + ret = FALSE; + if (mPlib_Check_DigScoop(&pos) == TRUE) { + x = pos.x - insect->tools_actor.actor_class.world.position.x; + z = pos.z - insect->tools_actor.actor_class.world.position.z; + if (((x * x) + (z * z)) < 4900.0f) { + ret = TRUE; + } + } + return ret; +} + +static int aIBT_check_patience(aINS_INSECT_ACTOR* insect, GAME* game) { + int ret; + + ret = FALSE; + + if (aIBT_check_ball(insect) == TRUE) { + insect->patience = 100.0f; + } else if (aIBT_check_player_net2(insect) == TRUE) { + insect->patience = 100.0f; + } else if (aIBT_check_player_scoop(insect) == TRUE) { + insect->patience = 100.0f; + } + if (insect->patience >= 90.0f) { + ret = TRUE; + } + return ret; +} + +static void aIBT_chk_avoid_jump_angle(ACTOR* actor, s16 chkAngle) { + aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*) actor; + s16 currentAngle = chkAngle; + + if (insect->tools_actor.actor_class.bg_collision_check.result.hit_wall & mCoBG_HIT_WALL_FRONT) { + currentAngle = insect->tools_actor.actor_class.world.angle.y; + currentAngle += (((((RANDOM(2)) * 2) - 1) << 0xE)); + } + insect->tools_actor.actor_class.world.angle.y = currentAngle; + insect->tools_actor.actor_class.shape_info.rotation.y = currentAngle; +} + +static void aIBT_set_avoid_jump_spd(aINS_INSECT_ACTOR* insect) { + s_xyz angle; + f32 mod; + int absRot; + + switch (insect->type) { + case aSOI_INSECT_TYPE_MIGRATORY_LOCUST: + insect->tools_actor.actor_class.speed = 7.5f; + insect->tools_actor.actor_class.position_speed.y = 9.0f; + insect->tools_actor.actor_class.gravity = 0.6f; + break; + default: + mod = 3.0f; + absRot = ABS(insect->tools_actor.actor_class.shape_info.rotation.y); + if (absRot > 0x4000) { + mCoBG_GetBgY_AngleS_FromWpos(&angle, insect->tools_actor.actor_class.world.position, 0.0f); + if (angle.x > 0) { + mod += (3.0f * sin_s(angle.x)); + } + } + insect->tools_actor.actor_class.speed = 5.0f; + insect->tools_actor.actor_class.position_speed.y = mod; + insect->tools_actor.actor_class.gravity = 0.3f; + break; + } +} + +static int aIBT_chk_active_range(s16* range, aINS_INSECT_ACTOR* insect) { + f32 z, x; + int ret; + + ret = TRUE; + x = insect->f32_work2 - insect->tools_actor.actor_class.world.position.x; + z = insect->f32_work3 - insect->tools_actor.actor_class.world.position.z; + if (((x * x) + (z * z)) >= 57600.0f) { + if (range != NULL) { + *range = atans_table(z, x); + } + ret = FALSE; + } + return ret; +} + +static void aIBT_avoid(ACTOR* actor, GAME* game) { + aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actor; + GAME_PLAY* play = (GAME_PLAY*)game; + + PLAYER_ACTOR* player; + f32 timer; + s16 angle; + + aIBT_anime_proc(insect); + if (insect->tools_actor.actor_class.bg_collision_check.result.is_in_water) { + aIBT_setupAction(insect, aIBT_ACTION_IN_WATER, &play->game); + } else if ((aIBT_check_player_net(insect) == FALSE) && + (insect->tools_actor.actor_class.bg_collision_check.result.on_ground)) { + if (insect->timer > 0) { + insect->timer--; + insect->tools_actor.actor_class.speed = 0.0f; + } else { + insect->timer = 8; + if (insect->patience < 85.0f) { + timer = 5.0f + (RANDOM_F(10.0f)); + insect->timer = (2.0f * timer); + aIBT_setupAction(insect, aIBT_ACTION_CHANGE_DIRECTION, &play->game); + + } else { + if (aIBT_chk_active_range(&angle, insect) == TRUE) { + player = GET_PLAYER_ACTOR(play); + if (player != NULL) { + angle = search_position_angleY(&insect->tools_actor.actor_class.world.position, + &player->actor_class.world.position) + + 0x8000; + } else { + angle = insect->tools_actor.actor_class.shape_info.rotation.y; + } + } + aIBT_chk_avoid_jump_angle(actor, angle); + aIBT_set_avoid_jump_spd(insect); + } + } + } +} + +static void aIBT_let_escape(ACTOR* actor, GAME* game) { + aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actor; + + aIBT_anime_proc(insect); + if (insect->tools_actor.actor_class.bg_collision_check.result.is_in_water) { + aIBT_setupAction(insect, aIBT_ACTION_IN_WATER, game); + } else { + if (insect->tools_actor.actor_class.bg_collision_check.result.on_ground) { + if (insect->timer > 0) { + insect->timer--; + insect->tools_actor.actor_class.speed = 0.0f; + } else { + insect->timer = 8; + aIBT_chk_avoid_jump_angle(actor, insect->tools_actor.actor_class.world.angle.y); + aIBT_set_avoid_jump_spd(insect); + } + } else { + aIBT_set_fly_se(insect); + } + } +} + +static void aIBT_chg_direction(ACTOR* actor, GAME* game) { + aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actor; + GAME_PLAY* play = (GAME_PLAY*)game; + + static f32 range[] = { + 4096.0f, 4096.0f, 8192.0f, 8192.0f, 8192.0f, 12288.0f, 12288.0f, 12288.0f, 12288.0f, + 12288.0f, 16384.0f, 16384.0f, 16384.0f, 16384.0f, 16384.0f, 16384.0f, + }; + + u32 attr; + xyz_t pos; + f32 mod; + s16 angle; + f32 bgY; + f32 yDir; + if (aIBT_chk_active_range(&angle, insect) == FALSE) { + insect->tools_actor.actor_class.world.angle.y = angle; + aIBT_setupAction(insect, aIBT_ACTION_WAIT, game); + } else { + angle = insect->tools_actor.actor_class.shape_info.rotation.y + 0x8000; + angle += (s16)(range[insect->s32_work0] * (2.0f * (fqrand() - 0.5f))); + xyz_t_move(&pos, &insect->tools_actor.actor_class.world.position); + mod = 53.0f; + if (insect->type == aSOI_INSECT_TYPE_MIGRATORY_LOCUST) { + mod = 218.0f; + } + pos.x += (mod * sin_s(angle)); + pos.z += (mod * cos_s(angle)); + bgY = mCoBG_GetBgY_AngleS_FromWpos(NULL, pos, 0.0f); + attr = mCoBG_Wpos2Attribute(pos, NULL); + yDir = insect->tools_actor.actor_class.world.position.y - bgY; + yDir = (yDir >= 0.0f) ? yDir : -yDir; + if ((yDir < 40.0f) && (mCoBG_CheckWaterAttribute(attr) == FALSE)) { + insect->tools_actor.actor_class.world.angle.y = angle; + aIBT_setupAction(insect, aIBT_ACTION_WAIT, game); + } else { + insect->s32_work0 += 1; + if (insect->s32_work0 > 0xF) { + aIBT_setupAction(insect, aIBT_ACTION_WAIT, game); + } + } + } +} + +static void aIBT_wait(ACTOR* actor, GAME* game) { + static u8 batta_sound_data[] = { + 159,158,160,157, + }; + GAME_PLAY* play; + aINS_INSECT_ACTOR* insect; + + + play = (GAME_PLAY*)game; + insect = (aINS_INSECT_ACTOR*)actor; + + + if (actor->bg_collision_check.result.is_in_water) { + aIBT_setupAction(insect, aIBT_ACTION_IN_WATER, game); + + } else if (aIBT_check_patience(insect,game) == TRUE) { + aIBT_setupAction(insect, aIBT_ACTION_AVOID, game); + } else { + f32 step = sqrtf(0.5); + + add_calc_short_angle2(&actor->shape_info.rotation.y, + actor->world.angle.y, 1.0f - step, 0x2000, 0); + + if ((insect->type >= 0xF) || (insect->type < 0xD)) { + int idx = insect->type - 15; + if ((actor->bg_collision_check.result.on_ground) && + (insect->patience < 20.0f)) { + if (insect->type == aSOI_INSECT_TYPE_BELL_CRICKET) { + aIBT_anime_proc(insect); + } + if (insect->s32_work1 == 0) { + sAdo_OngenPos((u32)insect, batta_sound_data[idx], &actor->world.position); + } + } + } + if (insect->timer > 0) { + insect->timer--; + + } else { + int action; + action = aIBT_ACTION_CHANGE_DIRECTION; + if (aIBT_chk_active_range(NULL, insect) == FALSE) { + action = aIBT_ACTION_JUMP; + } else { + if ((insect->type == aSOI_INSECT_TYPE_LONG_LOCUST) || (insect->type == aSOI_INSECT_TYPE_MIGRATORY_LOCUST)) { + if ((int)(play->game_frame % 200) > 20) { + action = aIBT_ACTION_JUMP; + } + } else if ((int)(play->game_frame % 200) < 20) { + action = aIBT_ACTION_JUMP; + } + } + aIBT_setupAction(insect, action, game); + } + } +} + +static void aIBT_jump(ACTOR* actor, GAME* game) { + aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actor; + GAME_PLAY* play = (GAME_PLAY*)game; + if (insect->tools_actor.actor_class.bg_collision_check.result.on_ground){ + aIBT_setupAction(insect, aIBT_ACTION_CHANGE_DIRECTION, game); + } +} + +static void aIBT_avoid_init(aINS_INSECT_ACTOR* insect, GAME* game) { + + GAME_PLAY* play = (GAME_PLAY*)game; + + s16 angle; + PLAYER_ACTOR* player; + player = get_player_actor_withoutCheck(play); + insect->tools_actor.actor_class.gravity = 0.2f; + insect->timer = 0; + if (player != NULL) { + angle = (search_position_angleY(&insect->tools_actor.actor_class.world.position, + &player->actor_class.world.position) - + 0x8000); + angle += (s16)(8192.0f * (2.0f * (fqrand() - 0.5f))); + insect->tools_actor.actor_class.shape_info.rotation.y = angle; + insect->tools_actor.actor_class.world.angle.y = angle; + + } +} + +static void aIBT_let_escape_init(aINS_INSECT_ACTOR* insect, GAME* game) { + PLAYER_ACTOR* player; + s16 chkAngle; + GAME_PLAY* play = (GAME_PLAY*)game; + + player = get_player_actor_withoutCheck(play); + insect->life_time = 0; + insect->alpha_time = 80; + insect->tools_actor.actor_class.gravity = 0.2f; + insect->timer = 0; + insect->tools_actor.actor_class.speed = 5.0f; + insect->tools_actor.actor_class.position_speed.y = 3.0f; + + if (player != NULL) { + chkAngle = player->actor_class.shape_info.rotation.y + (s16)(21845.0f * (fqrand() - 0.5f)); + insect->tools_actor.actor_class.world.angle.y = chkAngle; + insect->tools_actor.actor_class.shape_info.rotation.y = chkAngle; + } + insect->insect_flags.bit_1 = TRUE; + insect->insect_flags.bit_2 = TRUE; +} + +static void aIBT_chg_direction_init(aINS_INSECT_ACTOR* insect, GAME* game) { + insect->s32_work0 = 0; + insect->_1E0 = 0.0f; + insect->tools_actor.actor_class.speed = 0.0f; +} + +static void aIBT_wait_init(aINS_INSECT_ACTOR* insect, GAME* game) { + GAME_PLAY* play = (GAME_PLAY*)game; + + if (aIBT_chk_active_range(NULL, insect) == FALSE) { + insect->timer = 60; + } + else{ + insect->timer = (2.0f * (120.0f + (play->game_frame % 240))); + } +} + +static void aIBT_jump_init(aINS_INSECT_ACTOR* insect, GAME* game) { + insect->tools_actor.actor_class.position_speed.y = 4.0f; + insect->tools_actor.actor_class.speed = 5.5f; + insect->tools_actor.actor_class.gravity = 0.7f; +} + + +static void aIBT_drown_init(aINS_INSECT_ACTOR* insect, GAME* game) { + xyz_t pos = insect->tools_actor.actor_class.world.position; + f32 height = mCoBG_GetWaterHeight_File(pos, "ac_ins_batta.c", 995); + + pos.y = height; + + eEC_CLIP->effect_make_proc(eEC_EFFECT_TURI_MIZU, pos, 1,insect->tools_actor.actor_class.world.angle.y, game, 0, 4, 0); + sAdo_OngenTrgStart(0x438,&insect->tools_actor.actor_class.world.position); + + insect->insect_flags.bit_1 = TRUE; + insect->insect_flags.destruct = TRUE; + insect->tools_actor.actor_class.shape_info.draw_shadow = FALSE; +} + +typedef void (*aIBT_INIT_PROC)(aINS_INSECT_ACTOR*, GAME*); + +static void aIBT_setupAction(aINS_INSECT_ACTOR* insect, int action, GAME* game) { + static aIBT_INIT_PROC init_proc[] = { + &aIBT_avoid_init, + &aIBT_let_escape_init, + &aIBT_chg_direction_init, + &aIBT_wait_init, + &aIBT_jump_init, + &aIBT_drown_init, + }; + + static aINS_ACTION_PROC act_proc[] = { + &aIBT_avoid, + &aIBT_let_escape, + &aIBT_chg_direction, + &aIBT_wait, + &aIBT_jump, + (aINS_ACTION_PROC)&none_proc1, + }; + + insect->action = action; + insect->action_proc = act_proc[action]; + (*init_proc[action])(insect, game); +} + +void aIBT_actor_move(ACTOR* actor, GAME* game) { + aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actor; + GAME_PLAY* play = (GAME_PLAY*)game; + + u32 label = mPlib_Get_item_net_catch_label(); + + if (label == (u32)actor) { + aIBT_setupAction(insect, aIBT_ACTION_LET_ESCAPE, game); + } else { + if (insect->insect_flags.bit_3 == TRUE && insect->insect_flags.bit_2 == FALSE) { + aIBT_setupAction(insect, aIBT_ACTION_LET_ESCAPE, game); + } + else + insect->action_proc(actor,game); + } +} + +static void aIBT_actor_first_move(ACTOR* actor, GAME* game) { + aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actor; + if ((insect->flag < 2) && (aIBT_check_live_condition(insect) == TRUE)) { + insect->flag++; + if (insect->flag == 2) { + insect->tools_actor.actor_class.mv_proc = aIBT_actor_move; + } + aIBT_actor_move(actor, game); + } +} \ No newline at end of file