mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-09-12 11:35:12 -04:00
295 lines
9.3 KiB
Plaintext
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);
|
|
}
|
|
}
|