Merge pull request #335 from Cuyler36:ac_ins_ka

Implement & link ac_ins_ka
This commit is contained in:
Cuyler36
2024-04-30 15:02:50 -04:00
committed by GitHub
5 changed files with 322 additions and 0 deletions
+4
View File
@@ -778,6 +778,10 @@ ac_ins_hitodama.c:
.text: [0x8059A8E8, 0x8059B354]
.rodata: [0x8064A090, 0x8064A108]
.data: [0x806C3460, 0x806C34B0]
ac_ins_ka.c:
.text: [0x8059C174, 0x8059C9EC]
.rodata: [0x8064A1A8, 0x8064A1F0]
.data: [0x806C3550, 0x806C3580]
ac_boat.c:
.text: [0x805A6CF4, 0x805A856C]
.rodata: [0x8064A5B0, 0x8064A630]
+17
View File
@@ -0,0 +1,17 @@
#ifndef AC_INS_KA_H
#define AC_INS_KA_H
#include "types.h"
#include "ac_insect_h.h"
#ifdef __cplusplus
extern "C" {
#endif
extern void aIKA_actor_init(ACTOR* actorx, GAME* game);
#ifdef __cplusplus
}
#endif
#endif
+3
View File
@@ -59,6 +59,7 @@ typedef enum audio_sound_effects {
NA_SE_60 = 0x60,
NA_SE_GASAGOSO = 0x69,
NA_SE_6A = 0x6A,
NA_SE_TOILE_CHAIR_STANDUP = 0x72,
@@ -69,6 +70,8 @@ typedef enum audio_sound_effects {
NA_SE_STONECOIN_ROLL = 0x7D,
NA_SE_STONECOIN_DRAG = 0x7E,
NA_SE_CF = 0xCF,
NA_SE_ROD_STROKE = 0x109,
NA_SE_ROD_BACK,
+2
View File
@@ -72,6 +72,8 @@ extern int mPlib_request_main_sitdown_type1(GAME* game, int direct, const xyz_t*
extern int mPlib_request_main_lie_bed_type1(GAME* game, int direct, const xyz_t* pos, int head_direct, int ftr_no);
extern void mPlib_change_player_cloth(GAME* game, int idx);
extern u32 mPlib_Get_item_net_catch_label(void);
extern int mPlib_Check_stung_mosquito(ACTOR* actorx);
extern int mPlib_request_main_stung_mosquito_type1(ACTOR* actorx);
extern mPlayer_change_data_from_submenu_c* mPlib_Get_change_data_from_submenu_p();
+296
View File
@@ -0,0 +1,296 @@
#include "ac_ins_ka.h"
#include "m_field_info.h"
#include "m_name_table.h"
#include "m_common_data.h"
#include "m_player_lib.h"
enum {
aIKA_ACTION_AVOID,
aIKA_ACTION_LET_ESCAPE,
aIKA_ACTION_FLY,
aIKA_ACTION_SEARCH,
aIKA_ACTION_ATTACK_WAIT,
aIKA_ACTION_ATTACK,
aIKA_ACTION_NUM
};
#define aIKA_ATTACK_DIST (mFI_UNIT_BASE_SIZE_F / 2)
#define aIKA_ATTACK_TIME (180)
#define aIKA_IS_DEMO_ACTIVE() (Common_Get(clip).demo_clip != NULL || Common_Get(clip).demo_clip2 != NULL)
#define aIKA_RANDOM_ANGLE() ((s16)((fqrand() - 0.5f) * (f32)DEG2SHORT_ANGLE2(120.0f)))
#define aIKA_ANGLE(insect) ((insect)->s32_work0)
#define aIKA_ATTACK_TIMER(insect) ((insect)->s32_work1)
#define aIKA_TURN_SPEED(insect) ((insect)->f32_work0)
#define aIKA_SPEED(insect) ((insect)->f32_work1)
static void aIKA_setupAction(aINS_INSECT_ACTOR* insect, int action, GAME* game);
static void aIKA_actor_move(ACTOR* actorx, GAME* game);
extern void aIKA_actor_init(ACTOR* actorx, GAME* game) {
aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx;
int act;
if (actorx->actor_specific == 0) {
actorx->world.position.y = mCoBG_GetBgY_OnlyCenter_FromWpos(actorx->world.position, 30.0f);
act = aIKA_ACTION_FLY;
} else {
act = aIKA_ACTION_LET_ESCAPE;
}
insect->bg_range = 6.0f;
insect->bg_height = -14.0f;
insect->bg_type = 1;
insect->item = ITM_INSECT39;
xyz_t_move(&actorx->home.position, &actorx->world.position);
actorx->mv_proc = &aIKA_actor_move;
aIKA_setupAction(insect, act, game);
}
static void aIKA_fuwafuwa(aINS_INSECT_ACTOR* insect) {
s16 angle = aIKA_ANGLE(insect);
f32 last_spd_angle = aIKA_TURN_SPEED(insect) * sin_s(angle);
f32 now_spd_angle;
aIKA_ANGLE(insect) = (s16)(angle + 0x180);
if ((s16)(angle + 0x180) < 0 && angle >= 0) {
aIKA_TURN_SPEED(insect) = 10.0f + RANDOM_F(10.0f);
}
angle += 0x180;
now_spd_angle = aIKA_TURN_SPEED(insect) * sin_s(angle);
chase_f(&aIKA_SPEED(insect), insect->tools_actor.actor_class.max_velocity_y,
insect->tools_actor.actor_class.gravity * 0.5f);
insect->tools_actor.actor_class.position_speed.y = aIKA_SPEED(insect) + (now_spd_angle - last_spd_angle);
}
static void aIKA_anime_proc(aINS_INSECT_ACTOR* insect) {
insect->_1E0 += 0.2f;
if (insect->_1E0 >= 2.0f) {
insect->_1E0 -= 2.0f;
}
}
static void aIKA_BGcheck(aINS_INSECT_ACTOR* insect) {
if ((insect->tools_actor.actor_class.bg_collision_check.result.hit_wall & mCoBG_HIT_WALL_FRONT) != 0 ||
(insect->tools_actor.actor_class.bg_collision_check.result.hit_attribute_wall & mCoBG_HIT_WALL_FRONT) != 0 ||
(insect->tools_actor.actor_class.bg_collision_check.result.on_ground)) {
s16 new_dir = insect->tools_actor.actor_class.world.angle.y + DEG2SHORT_ANGLE2(180.0f); // turn around
insect->tools_actor.actor_class.world.angle.y = new_dir;
insect->tools_actor.actor_class.shape_info.rotation.y = new_dir;
}
}
static int aIKA_check_condition(aINS_INSECT_ACTOR* insect, GAME_PLAY* play) {
ACTOR* actorx = (ACTOR*)insect;
int res = FALSE;
if (actorx->block_x == play->block_table.block_x && actorx->block_z == play->block_table.block_z) {
if (ABS(actorx->player_distance_y) < 60.0f) {
res = TRUE;
}
}
return res;
}
static void aIKA_calc_angle_search_player(ACTOR* actorx, s16 step) {
s16 angle = actorx->shape_info.rotation.y;
chase_angle(&angle, actorx->player_angle_y, step);
actorx->shape_info.rotation.y = angle;
actorx->world.angle.y = angle;
}
static void aIKA_avoid(ACTOR* actorx, GAME* game) {
f32 grav = actorx->gravity;
grav *= 1.1f;
if (grav > 12.0f) {
grav = 12.0f;
}
actorx->gravity = grav;
}
static void aIKA_fly(ACTOR* actorx, GAME* game) {
aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
PLAYER_ACTOR* player = GET_PLAYER_ACTOR(play);
aIKA_BGcheck(insect);
/* Check that no demo is active */
if (aIKA_IS_DEMO_ACTIVE()) {
/* A demo is active (including chores), so despawn mosquito */
aIKA_setupAction(insect, aIKA_ACTION_AVOID, game);
} else if (player != NULL && aIKA_check_condition(insect, play) == TRUE) {
aIKA_setupAction(insect, aIKA_ACTION_SEARCH, game);
} else {
s16 angle = actorx->shape_info.rotation.y + 0x80;
actorx->shape_info.rotation.y = angle;
actorx->world.angle.y = angle;
}
}
static void aIKA_search(ACTOR* actorx, GAME* game) {
aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
/* Check that no demo is active */
if (aIKA_IS_DEMO_ACTIVE()) {
/* A demo is active (including chores), so despawn mosquito */
aIKA_setupAction(insect, aIKA_ACTION_AVOID, game);
} else if (aIKA_check_condition(insect, play) == FALSE) {
aIKA_setupAction(insect, aIKA_ACTION_FLY, game);
} else if (actorx->player_distance_xz <= aIKA_ATTACK_DIST) {
aIKA_setupAction(insect, aIKA_ACTION_ATTACK_WAIT, game);
} else {
s16 step;
if (actorx->player_distance_xz <= mFI_UNIT_BASE_SIZE_F) {
step = 0x100;
} else {
step = 0x200;
}
aIKA_calc_angle_search_player(actorx, step);
}
}
static void aIKA_attack_wait(ACTOR* actorx, GAME* game) {
aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
/* Check that no demo is active */
if (aIKA_IS_DEMO_ACTIVE()) {
/* A demo is active (including chores), so despawn mosquito */
aIKA_setupAction(insect, aIKA_ACTION_AVOID, game);
} else if (aIKA_check_condition(insect, play) == FALSE) {
aIKA_setupAction(insect, aIKA_ACTION_FLY, game);
} else if (actorx->player_distance_xz > aIKA_ATTACK_DIST) {
aIKA_setupAction(insect, aIKA_ACTION_SEARCH, game);
} else {
aIKA_calc_angle_search_player(actorx, 0x600);
aIKA_ATTACK_TIMER(insect)++;
if (aIKA_ATTACK_TIMER(insect) > aIKA_ATTACK_TIME) {
if (mPlib_Check_stung_mosquito(actorx)) {
aIKA_setupAction(insect, aIKA_ACTION_ATTACK, game);
} else {
mPlib_request_main_stung_mosquito_type1(actorx);
aIKA_ATTACK_TIMER(insect) = aIKA_ATTACK_TIME;
}
}
}
}
static void aIKA_attack(ACTOR* actorx, GAME* game) {
if (mPlib_Check_stung_mosquito(actorx) == FALSE) {
aIKA_setupAction((aINS_INSECT_ACTOR*)actorx, aIKA_ACTION_AVOID, game);
}
}
static void aIKA_avoid_init(aINS_INSECT_ACTOR* insect, GAME* game) {
ACTOR* actorx = (ACTOR*)insect;
GAME_PLAY* play = (GAME_PLAY*)game;
PLAYER_ACTOR* player;
insect->life_time = 0;
insect->alpha_time = 80;
actorx->gravity = 0.06f;
actorx->max_velocity_y = 12.0f;
actorx->speed = 4.0f;
actorx->shape_info.rotation.x = 0;
aIKA_SPEED(insect) = actorx->position_speed.y;
player = GET_PLAYER_ACTOR(play);
if (player != NULL) {
s16 rnd_angle = player->actor_class.shape_info.rotation.y + aIKA_RANDOM_ANGLE();
actorx->world.angle.y = rnd_angle;
actorx->shape_info.rotation.y = rnd_angle;
}
insect->insect_flags.bit_1 = TRUE;
insect->insect_flags.bit_2 = TRUE;
}
static void aIKA_fly_init(aINS_INSECT_ACTOR* insect, GAME* game) {
insect->tools_actor.actor_class.speed = 1.2f;
}
static void aIKA_attack_wait_init(aINS_INSECT_ACTOR* insect, GAME* game) {
aIKA_ATTACK_TIMER(insect) = 0;
}
static void aIKA_attack_init(aINS_INSECT_ACTOR* insect, GAME* game) {
insect->tools_actor.actor_class.speed = 0.0f;
insect->target_speed = 0.0f;
insect->speed_step = 0.0f;
insect->tools_actor.actor_class.position_speed.y = 0.0f;
sAdo_OngenTrgStart(NA_SE_6A, &insect->tools_actor.actor_class.world.position);
}
typedef void (*aIKA_INIT_PROC)(aINS_INSECT_ACTOR*, GAME*);
static void aIKA_setupAction(aINS_INSECT_ACTOR* insect, int action, GAME* game) {
// clang-format off
static aIKA_INIT_PROC init_proc[] = {
&aIKA_avoid_init,
&aIKA_avoid_init,
&aIKA_fly_init,
(aIKA_INIT_PROC)&none_proc1,
&aIKA_attack_wait_init,
&aIKA_attack_init,
};
// clang-format on
// clang-format off
static aINS_ACTION_PROC act_proc[] = {
&aIKA_avoid,
&aIKA_avoid,
&aIKA_fly,
&aIKA_search,
&aIKA_attack_wait,
&aIKA_attack,
};
// clang-format on
insect->action = action;
insect->action_proc = act_proc[action];
(*init_proc[action])(insect, game);
}
static void aIKA_actor_move(ACTOR* actorx, GAME* game) {
aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
u32 label;
if (mPlib_get_player_actor_main_index(game) != mPlayer_INDEX_PUTAWAY_NET && insect->action != aIKA_ACTION_ATTACK) {
aIKA_anime_proc(insect);
aIKA_fuwafuwa(insect);
} else {
insect->_1E0 = 0;
}
label = mPlib_Get_item_net_catch_label();
if (label == (u32)actorx) {
aIKA_setupAction(insect, aIKA_ACTION_LET_ESCAPE, game);
} else {
if (insect->action != aIKA_ACTION_ATTACK) {
sAdo_OngenPos((u32)actorx, NA_SE_CF, &actorx->world.position);
}
if (insect->insect_flags.bit_3 == TRUE && insect->insect_flags.bit_2 == FALSE &&
insect->action != aIKA_ACTION_LET_ESCAPE) {
aIKA_setupAction(insect, aIKA_ACTION_LET_ESCAPE, game);
} else {
(*insect->action_proc)(actorx, game);
}
}
}