Files
ac-decomp/src/ac_ev_ghost.c
T
2024-01-17 13:26:54 -05:00

307 lines
7.3 KiB
C

#include "ac_ev_ghost.h"
#include "m_event.h"
#include "m_common_data.h"
#include "m_msg.h"
#include "m_string.h"
#include "libultra/libultra.h"
#include "m_player_lib.h"
#include "m_item_name.h"
#include "m_house.h"
enum {
aEGH_TALK_END_WAIT,
aEGH_TALK_GIVE_ME_WAIT,
aEGH_TALK_SELECT_WAIT,
aEGH_TALK_SELECT_ROOF,
aEGH_TALK_GIVE_YOU_WAIT,
aEGH_TALK_CLEAR_GRASS,
aEGH_TALK_NUM
};
enum {
aEGH_THINK_NORMAL_WAIT,
aEGH_THINK_IRAI,
aEGH_THINK_IRAI_AF,
aEGH_THINK_BYE,
aEGH_THINK_WELCOM,
aEGH_THINK_BYEBYE,
aEGH_THINK_SPEAK, // ?
aEGH_THINK_NUM
};
enum {
aEGH_THINK_INIT_NONE,
aEGH_THINK_INIT_NORMAL_WAIT,
aEGH_THINK_INIT_IRAI,
aEGH_THINK_INIT_IRAI_AF,
aEGH_THINK_INIT_BYE,
aEGH_THINK_INIT_WELCOM,
aEGH_THINK_INIT_BYEBYE,
aEGH_THINK_INIT_NUM
};
enum {
aEGH_THINK_PROC_NONE,
aEGH_THINK_PROC_IRAI,
aEGH_THINK_PROC_BYE,
aEGH_THINK_PROC_BYEBYE,
aEGH_THINK_PROC_SPEAK_BYEBYE,
aEGH_THINK_PROC_NUM
};
enum {
aEGH_TALK_REQUEST_NONE,
aEGH_TALK_REQUEST_NORM,
aEGH_TALK_REQUEST_FORCE,
aEGH_TALK_REQUEST_NUM
};
typedef struct ghost_think_setup_s {
u8 think_proc;
u8 think_init_proc;
u8 talk_request_proc;
u8 talk_act;
u8 talk_after_act;
} aEGH_setup_c;
static void aEGH_actor_ct(ACTOR*, GAME*);
static void aEGH_actor_dt(ACTOR*, GAME*);
static void aEGH_actor_move(ACTOR*, GAME*);
static void aEGH_actor_draw(ACTOR*, GAME*);
static void aEGH_actor_init(ACTOR*, GAME*);
static void aEGH_actor_save(ACTOR*, GAME*);
ACTOR_PROFILE Ev_Ghost_Profile = {
mAc_PROFILE_EV_GHOST,
ACTOR_PART_NPC,
ACTOR_STATE_NONE,
SP_NPC_EV_GHOST,
ACTOR_OBJ_BANK_KEEP,
sizeof(EV_GHOST_ACTOR),
&aEGH_actor_ct,
&aEGH_actor_dt,
&aEGH_actor_init,
mActor_NONE_PROC1,
&aEGH_actor_save
};
static int aEGH_talk_init(ACTOR*, GAME*);
static int aEGH_talk_end_chk(ACTOR*, GAME*);
static int aEGH_change_talk_proc(EV_GHOST_ACTOR* ghost, u8 talk_act);
static void aEGH_setup_think_proc(EV_GHOST_ACTOR* ghost, GAME_PLAY* play, u8 think_act);
static void aEGH_schedule_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int sched_type);
static int aEGH_bitset_func(u16 bit);
static int aEGH_bitclr_func(u16 bit);
static u16 aEGH_bitcheck_func(u16 bit);
static void aEGH_byebye_check(EV_GHOST_ACTOR* ghost, GAME_PLAY* play);
static void aEGH_actor_ct(ACTOR* actorx, GAME* game) {
static aNPC_ct_data_c ct_data = {
&aEGH_actor_move,
&aEGH_actor_draw,
5,
(aNPC_TALK_REQUEST_PROC)&none_proc1,
&aEGH_talk_init,
&aEGH_talk_end_chk,
0
};
mEv_gst_c* ghost_save = (mEv_gst_c*)mEv_get_save_area(mEv_EVENT_GHOST, 54);
EV_GHOST_ACTOR* ghost = (EV_GHOST_ACTOR*)actorx;
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
if ((*Common_Get(clip).npc_clip->birth_check_proc)(actorx, game) == TRUE) {
ghost->npc_class.schedule.schedule_proc = &aEGH_schedule_proc;
(*Common_Get(clip).npc_clip->ct_proc)(actorx, game, &ct_data);
ghost->npc_class.palActorIgnoreTimer = -1;
ghost->_9A7 = 0;
ghost->melody_inst = 0;
ghost->npc_class.talk_info.melody_inst = 0;
if (ghost_save == NULL) {
mEv_reserve_save_area(mEv_EVENT_GHOST, 54);
ghost_save = (mEv_gst_c*)mEv_get_save_area(mEv_EVENT_GHOST, 54);
if (ghost_save != NULL) {
ghost_save->flags = 0;
ghost_save->okoruhito_str_no = RANDOM_F(32.0f);
mTM_set_renew_time(&ghost_save->renew_time, rtc_time);
}
}
else {
if (
rtc_time->year != ghost_save->renew_time.year ||
rtc_time->month != ghost_save->renew_time.month ||
rtc_time->day != ghost_save->renew_time.day
) {
ghost_save->flags = 0;
ghost_save->okoruhito_str_no = RANDOM_F(32.0f);
mTM_set_renew_time(&ghost_save->renew_time, rtc_time);
}
if ((ghost_save->flags & mEv_GHOST_FLAG_RETURNED_SPIRITS) != 0) {
Actor_delete(actorx);
}
}
if (Common_Get(player_no) == mPr_FOREIGNER) {
Actor_delete(actorx);
}
ghost->_9AA = 0;
ghost->npc_class.talk_info.default_animation = 126;
ghost->_9AC = 0;
if (aEGH_bitcheck_func(aEGH_BIT_FOUND_GHOST) != FALSE) {
ghost->alpha = 140;
}
else {
if (mFI_GetItemNumField_BCT(GRASS_A, GRASS_C) < aEGH_MINIMUM_GRASS_COUNT) {
Actor_delete(actorx);
}
ghost->alpha = 0;
}
}
}
static void aEGH_actor_save(ACTOR* actorx, GAME* game) {
mNpc_RenewalSetNpc(actorx);
}
static void aEGH_actor_dt(ACTOR* actorx, GAME* game) {
mEv_actor_dying_message(mEv_EVENT_GHOST, actorx);
(*Common_Get(clip).npc_clip->dt_proc)(actorx, game);
}
static void aEGH_actor_init(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->init_proc)(actorx, game);
}
static int aEGH_set_request_act(EV_GHOST_ACTOR* ghost, u8 priority, u8 idx, u8 type, u16 arg0, u16 arg1, u16 arg2) {
int res = FALSE;
if (priority >= ghost->npc_class.request.act_priority) {
u16 args[6];
bzero(args, sizeof(args));
args[0] = arg0;
args[2] = arg1;
args[3] = arg2;
ghost->npc_class.request.act_priority = priority;
ghost->npc_class.request.act_idx = idx;
ghost->npc_class.request.act_type = type;
mem_copy((u8*)ghost->npc_class.request.act_args, (u8*)args, sizeof(args));
res = TRUE;
}
return res;
}
static void aEGH_actor_move(ACTOR* actorx, GAME* game) {
EV_GHOST_ACTOR* ghost = (EV_GHOST_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
int step;
int alpha;
int target_alpha;
int delta_alpha;
if (aEGH_bitcheck_func(aEGH_BIT_FOUND_GHOST) != FALSE) {
actorx->actor_specific = 1;
}
else {
actorx->actor_specific = 0;
}
(*Common_Get(clip).npc_clip->move_proc)(actorx, game);
aEGH_byebye_check(ghost, play);
if (ghost->npc_class.schedule.type == aNPC_SCHEDULE_TYPE_WALK_WANDER && ghost->think_act != aEGH_THINK_SPEAK) {
ghost->_9AC = 1;
(*Common_Get(clip).npc_clip->chg_schedule_proc)((NPC_ACTOR*)ghost, play, aNPC_SCHEDULE_TYPE_SPECIAL);
actorx->status_data.weight = 255;
}
alpha = ghost->alpha;
if (aEGH_bitcheck_func(aEGH_BIT_FOUND_GHOST) != FALSE) {
step = 1;
if (mDemo_Get_talk_actor() == actorx) {
ghost->npc_class.draw._5BE = 0;
ghost->npc_class.draw.animation_speed = 0.5f;
target_alpha = 190;
}
else {
if (actorx->speed > 0.1f) {
target_alpha = 80;
}
else {
target_alpha = 140;
}
if (alpha <= 140) {
step = 1;
}
ghost->npc_class.draw._5BE = 1;
ghost->npc_class.draw.animation_speed = 0.25f;
}
delta_alpha = alpha - target_alpha;
if (ABS(delta_alpha) < step) {
alpha = target_alpha;
}
else {
if (delta_alpha < 0) {
alpha += step;
}
else {
alpha -= step;
}
}
}
else if (ghost->bye_bye_transparency_delay_timer != 0) {
ghost->bye_bye_transparency_delay_timer--;
}
else {
alpha -= 4;
if (alpha < 0) {
alpha = 0;
}
}
ghost->alpha = alpha;
actorx->shape_info.draw_shadow = FALSE;
}
static void aEGH_actor_draw(ACTOR* actorx, GAME* game) {
EV_GHOST_ACTOR* ghost = (EV_GHOST_ACTOR*)actorx;
GRAPH* graph = game->graph;
Gfx* gfx;
OPEN_DISP(graph);
gfx = NOW_POLY_XLU_DISP;
gDPPipeSync(gfx++);
gDPSetEnvColor(gfx++, 255, 255, 255, ghost->alpha);
SET_POLY_XLU_DISP(gfx);
CLOSE_DISP(graph);
(*Common_Get(clip).npc_clip->draw_proc)(actorx, game);
}
#include "../src/ac_ev_ghost_talk.c_inc"
#include "../src/ac_ev_ghost_schedule.c_inc"