Files
ac-decomp/src/actor/npc/ac_npc2_move.c_inc
T
2025-01-06 17:06:26 -05:00

295 lines
9.3 KiB
Plaintext

static f32 aNPC_get_rev_val(f32 rev, f32 amount) {
if (ABS(rev) >= amount) {
if (rev < 0.0f) {
return -amount;
} else {
return amount;
}
} else {
return rev;
}
}
static void aNPC_BGcheck(NPC_ACTOR* nactorx, ACTOR* actorx) {
if ((nactorx->condition_info.demo_flg & aNPC_COND_DEMO_SKIP_BGCHECK) == 0) {
if (ClObj_DID_COLLIDE(nactorx->collision.pipe.collision_obj)) {
mCoBG_BgCheckControll(NULL, actorx, nactorx->collision.BGcheck_radius, 0.0f, TRUE, FALSE, 0);
nactorx->collision.bg_rev_add = 0.0f;
} else {
xyz_t rev;
f32 amount;
mCoBG_BgCheckControll(&rev, actorx, nactorx->collision.BGcheck_radius, 0.0f, TRUE, TRUE, 0);
amount = nactorx->collision.bg_rev_add;
amount += 1.0f;
if (amount > 4.0f) {
amount = 4.0f;
}
nactorx->collision.bg_rev_add = amount;
actorx->world.position.x += aNPC_get_rev_val(rev.x, amount);
actorx->world.position.y += aNPC_get_rev_val(rev.y, amount);
actorx->world.position.z += aNPC_get_rev_val(rev.z, amount);
}
} else {
mCoBG_InitBgCheckResult(&actorx->bg_collision_check.result);
nactorx->collision.bg_rev_add = 0.0f;
}
}
static void aNPC_set_over_friendship(NPC_ACTOR* nactorx) {
if (ITEM_NAME_GET_TYPE(nactorx->actor_class.npc_id) != NAME_TYPE_SPNPC) {
int over_friendship = 0;
switch (Now_Private->destiny.type) {
case mPr_DESTINY_UNPOPULAR:
over_friendship = -0x100;
break;
case mPr_DESTINY_POPULAR:
if (mNpc_GetLooks2Sex(nactorx->npc_info.animal->id.looks) != Now_Private->gender) {
over_friendship = 0x100;
}
break;
}
nactorx->condition_info.over_friendship = over_friendship;
}
}
static void aNPC_set_mv_angl(NPC_ACTOR* nactorx) {
s16 angle = atans_table(nactorx->movement.avoid_pos_z - nactorx->actor_class.world.position.z,
nactorx->movement.avoid_pos_x - nactorx->actor_class.world.position.x);
nactorx->movement.mv_angl = angle;
}
static void aNPC_set_avoid_pos(NPC_ACTOR* nactorx, f32 avoid_pos_x, f32 avoid_pos_z) {
nactorx->movement.avoid_pos_x = avoid_pos_x;
nactorx->movement.avoid_pos_z = avoid_pos_z;
aNPC_set_mv_angl(nactorx);
}
static void aNPC_set_dst_pos(NPC_ACTOR* nactorx, f32 dst_pos_x, f32 dst_pos_z) {
nactorx->movement.dst_pos_x = dst_pos_x;
nactorx->movement.dst_pos_z = dst_pos_z;
nactorx->movement.move_timer = 0;
aNPC_set_avoid_pos(nactorx, dst_pos_x, dst_pos_z);
}
static void aNPC_check_feel_tim(NPC_ACTOR* nactorx) {
Animal_c* animal_p = nactorx->npc_info.animal;
if (animal_p != NULL) {
if ((nactorx->condition_info.demo_flg & aNPC_COND_DEMO_SKIP_FEEL_CHECK) == 0 &&
nactorx->condition_info.feel_tim > 0) {
nactorx->condition_info.feel_tim--;
}
if (nactorx->condition_info.feel_tim == 0) {
animal_p->mood = mNpc_FEEL_NORMAL;
}
}
}
static void aNPC_calc_force_call_timer(NPC_ACTOR* nactorx) {
if (mDemo_Get_talk_actor() == NULL && nactorx->think.force_call_timer != 0) {
nactorx->think.force_call_timer--;
}
}
static void aNPC_calc_timer(NPC_ACTOR* nactorx) {
aNPC_calc_force_call_timer(nactorx);
}
static void aNPC_position_move(ACTOR* actorx) {
NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx;
f32 accel;
if (actorx->speed < nactorx->movement.speed.max_speed) {
accel = nactorx->movement.speed.acceleration;
} else {
accel = nactorx->movement.speed.deceleration;
}
chase_f(&actorx->speed, nactorx->movement.speed.max_speed, accel * 0.5f);
#ifndef aNPC_NPC2
Actor_position_speed_set(actorx);
#else
Actor_position_moveF(actorx);
#endif
}
static void aNPC_angle_calc(NPC_ACTOR* nactorx) {
chase_angle(&nactorx->actor_class.shape_info.rotation.y, nactorx->movement.mv_angl, nactorx->movement.mv_add_angl);
nactorx->actor_class.world.angle.y = nactorx->actor_class.shape_info.rotation.y;
}
static void aNPC_set_body_angle(NPC_ACTOR* nactorx) {
s16 angle;
if (nactorx->movement.override_body_angle_flag == TRUE) {
angle = nactorx->movement.body_angle;
} else {
angle = (nactorx->actor_class.speed * 3640.0f) / 3.0f;
}
chase_angle(&nactorx->actor_class.shape_info.rotation.x, angle, 224);
}
static void aNPC_calc_fatigue(NPC_ACTOR* nactorx) {
static int fatigue_add_table[] = {
-2, -2, -2, -2, -2, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
int fatigue = nactorx->condition_info.fatigue;
fatigue += fatigue_add_table[nactorx->condition_info.action];
if (fatigue < 0) {
fatigue = 0;
} else if (fatigue > 1600) {
fatigue = 1600;
}
nactorx->condition_info.fatigue = fatigue;
}
typedef struct {
int talk_flag;
s16 mv_angl_add;
u8 speed_type;
} aNPC_setup_data_c;
static void aNPC_setupAction(NPC_ACTOR* nactorx, u8 action) {
// clang-format off
static aNPC_setup_data_c setup_data[aNPC_ACTION_TYPE_NUM] = {
{FALSE, 0x0100, 0x00},
{FALSE, 0x0100, 0x00},
{FALSE, 0x0100, 0x00},
{FALSE, 0x0100, 0x00},
{FALSE, 0x0100, 0x00},
{FALSE, 0x0400, 0x01},
{FALSE, 0x0400, 0x01},
{FALSE, 0x0400, 0x01},
{FALSE, 0x0400, 0x01},
{FALSE, 0x0400, 0x02},
{FALSE, 0x0400, 0x02},
{FALSE, 0x0400, 0x02},
{FALSE, 0x0400, 0x02},
{FALSE, 0x0800, 0x00},
{FALSE, 0x0800, 0x00},
{FALSE, 0x0800, 0x00},
{ TRUE, 0x0400, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{FALSE, 0x0000, 0x00},
{ TRUE, 0x0000, 0x00},
};
// clang-format on
aNPC_setup_data_c* data_p = &setup_data[action];
aNPC_spd_c* speed_p = &aNPC_spd_data[data_p->speed_type];
nactorx->condition_info.action = action;
nactorx->movement.mv_add_angl = data_p->mv_angl_add;
nactorx->movement.speed.max_speed = speed_p->max_speed;
nactorx->movement.speed.acceleration = speed_p->acceleration;
nactorx->movement.speed.deceleration = speed_p->deceleration;
if (data_p->speed_type == 0) {
nactorx->actor_class.speed = 0.0f;
}
nactorx->talk_info.demo_code = aNPC_MANPU_CODE_NONE;
aNPC_Animation_init((ACTOR*)nactorx, aNPC_animeSeqNoTable[(int)action], data_p->talk_flag);
}
static void aNPC_actor_move_hide(ACTOR* actorx, GAME* game) {
NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
aNPC_schedule_proc(nactorx, play);
aNPC_action_proc(nactorx, play);
aNPC_check_feel_tim(nactorx);
}
static void aNPC_actor_move_show_before(ACTOR* actorx, GAME* game) {
NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx;
aNPC_anime_proc(nactorx, game);
aNPC_tex_anm_ctrl(nactorx);
aNPC_position_move(actorx);
aNPC_BGcheck(nactorx, actorx);
}
static void aNPC_actor_move_show_after(ACTOR* actorx, GAME* game) {
NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
aNPC_set_anime_speed(nactorx);
aNPC_set_body_angle(nactorx);
aNPC_check_feel_tim(nactorx);
aNPC_calc_timer(nactorx);
Actor_world_to_eye(actorx, nactorx->eye_y);
if ((nactorx->condition_info.demo_flg & aNPC_COND_DEMO_SKIP_OBJ_COL_CHECK) == 0) {
CollisionCheck_Uty_ActorWorldPosSetPipeC(actorx, &nactorx->collision.pipe);
CollisionCheck_setOC(game, &play->collision_check, &nactorx->collision.pipe.collision_obj);
}
}
static void aNPC_actor_move_show(ACTOR* actorx, GAME* game) {
NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
aNPC_set_over_friendship(nactorx);
aNPC_actor_move_show_before(actorx, game);
aNPC_schedule_proc(nactorx, play);
aNPC_action_proc(nactorx, play);
aNPC_talk_request_check(actorx, game);
aNPC_angle_calc(nactorx);
aNPC_calc_fatigue(nactorx);
aNPC_actor_move_show_after(actorx, game);
}
static void aNPC_actor_move(ACTOR* actorx, GAME* game) {
NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx;
if (nactorx->condition_info.hide_flg != nactorx->condition_info.hide_request) {
u8 hide_req = nactorx->condition_info.hide_request;
nactorx->condition_info.hide_flg = hide_req;
actorx->shape_info.draw_shadow = hide_req ^ 1;
}
if (nactorx->condition_info.hide_flg == TRUE) {
aNPC_actor_move_hide(actorx, game);
} else {
aNPC_actor_move_show(actorx, game);
}
}