mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-05-29 16:14:59 -04:00
Merge pull request #335 from Cuyler36:ac_ins_ka
Implement & link ac_ins_ka
This commit is contained in:
@@ -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]
|
||||
|
||||
@@ -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
|
||||
@@ -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,
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user