mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-05-25 07:02:50 -04:00
377 lines
10 KiB
Plaintext
377 lines
10 KiB
Plaintext
static void aEGH_look_player(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
|
|
if (ghost->npc_class.action.step == aNPC_ACTION_END_STEP) {
|
|
u8 action = 4;
|
|
s16 player_y = ghost->npc_class.actor_class.player_angle_y;
|
|
s16 rot_y = ghost->npc_class.actor_class.shape_info.rotation.y;
|
|
s16 diff = player_y - rot_y;
|
|
|
|
if (ABS(diff) < DEG2SHORT_ANGLE(67.5f)) {
|
|
action = 0;
|
|
}
|
|
|
|
aEGH_set_request_act(ghost, 4, action, 2, 1, 0, 0);
|
|
}
|
|
}
|
|
|
|
static int aEGH_bitset_func(u16 bit) {
|
|
u32 player_no = Common_Get(player_no);
|
|
mEv_gst_c* ghost_save = (mEv_gst_c*)mEv_get_save_area(mEv_EVENT_GHOST, 54);
|
|
mEv_gst_common_c* ghost_common = (mEv_gst_common_c*)mEv_get_common_area(mEv_EVENT_GHOST, 55);
|
|
|
|
if (player_no == mPr_FOREIGNER) {
|
|
if (ghost_common != NULL) {
|
|
ghost_common->flags |= bit;
|
|
return TRUE;
|
|
}
|
|
}
|
|
else if (ghost_save != NULL) {
|
|
ghost_save->flags |= (u16)(bit << player_no);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static int aEGH_bitclr_func(u16 bit) {
|
|
u32 player_no = Common_Get(player_no);
|
|
mEv_gst_c* ghost_save = (mEv_gst_c*)mEv_get_save_area(mEv_EVENT_GHOST, 54);
|
|
mEv_gst_common_c* ghost_common = (mEv_gst_common_c*)mEv_get_common_area(mEv_EVENT_GHOST, 55);
|
|
|
|
if (player_no == mPr_FOREIGNER) {
|
|
if (ghost_common != NULL) {
|
|
ghost_common->flags &= ~bit;
|
|
return TRUE;
|
|
}
|
|
}
|
|
else if (ghost_save != NULL) {
|
|
ghost_save->flags &= ~(u16)(bit << player_no);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static u16 aEGH_bitcheck_func(u16 bit) {
|
|
u32 player_no = Common_Get(player_no);
|
|
mEv_gst_c* ghost_save = (mEv_gst_c*)mEv_get_save_area(mEv_EVENT_GHOST, 54);
|
|
mEv_gst_common_c* ghost_common = (mEv_gst_common_c*)mEv_get_common_area(mEv_EVENT_GHOST, 55);
|
|
|
|
if (player_no == mPr_FOREIGNER) {
|
|
if (ghost_common != NULL) {
|
|
return ghost_common->flags & bit;
|
|
}
|
|
}
|
|
else if (ghost_save != NULL) {
|
|
return (u16)(bit << player_no) & ghost_save->flags;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static int aEGH_equal_block(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
|
|
int bx;
|
|
int bz;
|
|
|
|
mFI_Wpos2BlockNum(&bx, &bz, GET_PLAYER_ACTOR(play)->actor_class.world.position);
|
|
return bx == ghost->npc_class.actor_class.block_x && bz == ghost->npc_class.actor_class.block_z;
|
|
}
|
|
|
|
static int aEGH_time_over() {
|
|
return Common_Get(time.now_sec) > (4 * mTM_SECONDS_IN_HOUR);
|
|
}
|
|
|
|
static void aEGH_byebye_check(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
|
|
ACTOR* actorx = (ACTOR*)ghost;
|
|
|
|
if (
|
|
mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE &&
|
|
mDemo_Check(mDemo_TYPE_SPEAK, actorx) == FALSE &&
|
|
aEGH_time_over() != FALSE
|
|
) {
|
|
if (aEGH_equal_block(ghost, play)) {
|
|
switch (ghost->think_act) {
|
|
case aEGH_THINK_SPEAK:
|
|
{
|
|
aEGH_setup_think_proc(ghost, play, aEGH_THINK_BYEBYE);
|
|
ghost->msg_no = 0x2EDD;
|
|
ghost->npc_class.actor_class.talk_distance = 1000.0f;
|
|
ghost->_9AA = 1;
|
|
break;
|
|
}
|
|
|
|
case aEGH_THINK_NORMAL_WAIT:
|
|
case aEGH_THINK_IRAI_AF:
|
|
case aEGH_THINK_BYE:
|
|
case aEGH_THINK_WELCOM:
|
|
{
|
|
Actor_delete((ACTOR*)ghost);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
aEGH_setup_think_proc(ghost, play, aEGH_THINK_IRAI);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void aEGH_irai(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
|
|
if (ghost->npc_class.actor_class.player_distance_xz > 220.0f) {
|
|
aEGH_setup_think_proc(ghost, play, aEGH_THINK_BYE);
|
|
}
|
|
}
|
|
|
|
static void aEGH_bye(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
|
|
if (ghost->npc_class.actor_class.player_distance_xz < 200.0f) {
|
|
aEGH_setup_think_proc(ghost, play, aEGH_THINK_WELCOM);
|
|
}
|
|
}
|
|
|
|
static void aEGH_byebye(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
|
|
if (ghost->alpha == 0) {
|
|
Actor_delete((ACTOR*)ghost);
|
|
}
|
|
else {
|
|
if (ghost->bye_bye_timer != 0) {
|
|
ghost->bye_bye_timer--;
|
|
|
|
if (ghost->bye_bye_timer == 0) {
|
|
sAdo_SysTrgStart(0x16C);
|
|
}
|
|
}
|
|
else {
|
|
if (ghost->bye_bye_angle < 30000) {
|
|
ghost->bye_bye_angle += 60;
|
|
}
|
|
|
|
ghost->npc_class.actor_class.shape_info.rotation.y += ghost->bye_bye_angle;
|
|
ghost->npc_class.actor_class.world.angle.y = ghost->npc_class.actor_class.shape_info.rotation.y;
|
|
ghost->npc_class.movement.mv_angl = ghost->npc_class.actor_class.world.angle.y;
|
|
ghost->npc_class.movement.mv_add_angl = 0;
|
|
}
|
|
|
|
if (ghost->bye_bye_scale_timer != 0) {
|
|
ghost->bye_bye_scale_timer--;
|
|
}
|
|
else {
|
|
ghost->npc_class.actor_class.scale.x += -0.00004f;
|
|
ghost->npc_class.actor_class.scale.z = ghost->npc_class.actor_class.scale.x;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void aEGH_speak_byebye(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
|
|
ACTOR* actorx = (ACTOR*)ghost;
|
|
|
|
if (
|
|
mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE &&
|
|
mDemo_Check(mDemo_TYPE_SPEAK, actorx) == FALSE &&
|
|
aEGH_equal_block(ghost, play) == FALSE
|
|
) {
|
|
aEGH_setup_think_proc(ghost, play, aEGH_THINK_IRAI);
|
|
}
|
|
}
|
|
|
|
static void aEGH_think_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play) {
|
|
EV_GHOST_ACTOR* ghost = (EV_GHOST_ACTOR*)actorx;
|
|
|
|
(*ghost->think_proc)(ghost, play);
|
|
aEGH_look_player(ghost, play);
|
|
}
|
|
|
|
static void aEGH_think_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play) {
|
|
EV_GHOST_ACTOR* ghost = (EV_GHOST_ACTOR*)actorx;
|
|
u8 think_act;
|
|
|
|
if (ghost->_9AC) {
|
|
ghost->_9AC = FALSE;
|
|
}
|
|
else {
|
|
if (aEGH_bitcheck_func(aEGH_BIT_FOUND_GHOST)) {
|
|
ghost->alpha = 140;
|
|
think_act = aEGH_THINK_SPEAK;
|
|
}
|
|
else {
|
|
ghost->alpha = 0;
|
|
think_act = aEGH_THINK_IRAI_AF;
|
|
}
|
|
|
|
actorx->actor_class.status_data.weight = 255;
|
|
actorx->condition_info.hide_request = FALSE;
|
|
aEGH_setup_think_proc(ghost, play, think_act);
|
|
actorx->condition_info.demo_flg = aNPC_COND_DEMO_SKIP_FOOTSTEPS_VFX |
|
|
aNPC_COND_DEMO_SKIP_FEEL_CHECK |
|
|
aNPC_COND_DEMO_SKIP_FOOTSTEPS |
|
|
aNPC_COND_DEMO_SKIP_ENTRANCE_CHECK |
|
|
aNPC_COND_DEMO_SKIP_HEAD_LOOKAT;
|
|
}
|
|
}
|
|
|
|
static void aEGH_normal_wait_init(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
|
|
(*Common_Get(clip).npc_clip->animation_init_proc)((ACTOR*)ghost, 126, FALSE);
|
|
ghost->npc_class.draw.main_animation.keyframe.frame_control.mode = cKF_FRAMECONTROL_REPEAT;
|
|
ghost->npc_class.action.idx = 0;
|
|
aEGH_set_request_act(ghost, 4, 0, 0, 0, 0, 0);
|
|
}
|
|
|
|
static void aEGH_irai_init(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
|
|
ghost->npc_class.actor_class.talk_distance = 80.0f;
|
|
aEGH_normal_wait_init(ghost, play);
|
|
ghost->msg_no = 0x2EE2;
|
|
}
|
|
|
|
static void aEGH_irai_af_init(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
|
|
ghost->npc_class.actor_class.talk_distance = 55.0f;
|
|
ghost->msg_no = 0x2EE7;
|
|
(*Common_Get(clip).npc_clip->chg_schedule_proc)((NPC_ACTOR*)ghost, play, 5);
|
|
ghost->npc_class.actor_class.status_data.weight = 80;
|
|
}
|
|
|
|
static void aEGH_bye_init(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
|
|
ghost->npc_class.actor_class.talk_distance = 280.0f;
|
|
aEGH_normal_wait_init(ghost, play);
|
|
ghost->msg_no = 0x2ED8;
|
|
}
|
|
|
|
static void aEGH_welcom_init(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
|
|
ghost->npc_class.actor_class.talk_distance = 200.0f;
|
|
aEGH_normal_wait_init(ghost, play);
|
|
ghost->msg_no = 0x2ED3;
|
|
}
|
|
|
|
static void aEGH_byebye_init(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
|
|
aEGH_bitclr_func(aEGH_BIT_FOUND_GHOST);
|
|
ghost->bye_bye_angle = -1000;
|
|
ghost->bye_bye_timer = 25;
|
|
ghost->bye_bye_scale_timer = 48;
|
|
ghost->bye_bye_transparency_delay_timer = 43;
|
|
aEGH_normal_wait_init(ghost, play);
|
|
ghost->npc_class.head.lock_flag = TRUE;
|
|
}
|
|
|
|
static aEGH_setup_c dt_tbl[aEGH_THINK_NUM] = {
|
|
{
|
|
aEGH_THINK_PROC_BYE,
|
|
aEGH_THINK_INIT_NORMAL_WAIT,
|
|
aEGH_TALK_REQUEST_NONE,
|
|
aEGH_TALK_END_WAIT,
|
|
aEGH_THINK_NORMAL_WAIT
|
|
},
|
|
{
|
|
aEGH_THINK_PROC_BYEBYE,
|
|
aEGH_THINK_INIT_BYEBYE,
|
|
aEGH_TALK_REQUEST_NONE,
|
|
aEGH_TALK_END_WAIT,
|
|
aEGH_THINK_IRAI
|
|
},
|
|
|
|
{
|
|
aEGH_THINK_PROC_NONE,
|
|
aEGH_THINK_INIT_WELCOM,
|
|
aEGH_TALK_REQUEST_FORCE,
|
|
aEGH_TALK_END_WAIT,
|
|
aEGH_THINK_WELCOM
|
|
},
|
|
|
|
{
|
|
aEGH_THINK_PROC_BYE,
|
|
aEGH_THINK_INIT_BYE,
|
|
aEGH_TALK_REQUEST_FORCE,
|
|
aEGH_TALK_GIVE_ME_WAIT,
|
|
aEGH_THINK_NORMAL_WAIT
|
|
},
|
|
|
|
{
|
|
aEGH_THINK_PROC_IRAI,
|
|
aEGH_THINK_INIT_IRAI,
|
|
aEGH_TALK_REQUEST_FORCE,
|
|
aEGH_TALK_SELECT_WAIT,
|
|
aEGH_THINK_SPEAK
|
|
},
|
|
|
|
{
|
|
aEGH_THINK_PROC_SPEAK_BYEBYE,
|
|
aEGH_THINK_INIT_NORMAL_WAIT,
|
|
aEGH_TALK_REQUEST_FORCE,
|
|
aEGH_TALK_SELECT_ROOF,
|
|
aEGH_THINK_IRAI
|
|
},
|
|
|
|
{
|
|
aEGH_THINK_PROC_NONE,
|
|
aEGH_THINK_INIT_IRAI_AF,
|
|
aEGH_TALK_REQUEST_NORM,
|
|
aEGH_TALK_END_WAIT,
|
|
aEGH_THINK_SPEAK
|
|
}
|
|
};
|
|
|
|
static aEGH_PROC proc_table[aEGH_THINK_PROC_NUM] = {
|
|
(aEGH_PROC)&none_proc1,
|
|
&aEGH_irai,
|
|
&aEGH_bye,
|
|
&aEGH_byebye,
|
|
&aEGH_speak_byebye
|
|
};
|
|
|
|
static aEGH_PROC init_table[aEGH_THINK_INIT_NUM] = {
|
|
(aEGH_PROC)&none_proc1,
|
|
&aEGH_normal_wait_init,
|
|
&aEGH_irai_init,
|
|
&aEGH_irai_af_init,
|
|
&aEGH_bye_init,
|
|
&aEGH_welcom_init,
|
|
&aEGH_byebye_init
|
|
};
|
|
|
|
static void aEGH_setup_think_proc(EV_GHOST_ACTOR* ghost, GAME_PLAY* play, u8 think_act) {
|
|
static aNPC_TALK_REQUEST_PROC talk_request_table[aEGH_TALK_REQUEST_NUM] = {
|
|
(aNPC_TALK_REQUEST_PROC)&none_proc1,
|
|
&aEGH_norm_talk_request,
|
|
&aEGH_force_talk_request
|
|
};
|
|
|
|
aEGH_setup_c* data = &dt_tbl[think_act];
|
|
|
|
ghost->think_act = think_act;
|
|
ghost->think_proc = proc_table[data->think_proc];
|
|
ghost->npc_class.talk_info.talk_request_proc = talk_request_table[data->talk_request_proc];
|
|
ghost->talk_act = data->talk_act;
|
|
ghost->after_talk_think_act = data->talk_after_act;
|
|
(*init_table[data->think_init_proc])(ghost, play);
|
|
ghost->_9A7 = TRUE;
|
|
}
|
|
|
|
static void aEGH_think_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int think_type) {
|
|
switch (think_type) {
|
|
case 0:
|
|
aEGH_think_init_proc(actorx, play);
|
|
break;
|
|
case 1:
|
|
aEGH_think_main_proc(actorx, play);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void aEGH_schedule_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play) {
|
|
actorx->think.think_proc = &aEGH_think_proc;
|
|
(*Common_Get(clip).npc_clip->think_proc)(actorx, play, aNPC_THINK_SPECIAL, 0);
|
|
}
|
|
|
|
static void aEGH_schedule_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play) {
|
|
if ((*Common_Get(clip).npc_clip->think_proc)(actorx, play, -1, 1) == FALSE) {
|
|
(*Common_Get(clip).npc_clip->think_proc)(actorx, play, -1, 2);
|
|
}
|
|
}
|
|
|
|
static void aEGH_schedule_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int sched_type) {
|
|
switch (sched_type) {
|
|
case 0:
|
|
aEGH_schedule_init_proc(actorx, play);
|
|
break;
|
|
case 1:
|
|
aEGH_schedule_main_proc(actorx, play);
|
|
break;
|
|
}
|
|
}
|