From 6d6f15c493d3ed7577c3db9e0fba609699c243c4 Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Sun, 12 Nov 2023 21:04:35 -0500 Subject: [PATCH] Implement & link m_demo.c --- config/rel_slices.yml | 5 + include/MSL_C/math.h | 3 + include/m_actor.h | 1 + include/m_bgm.h | 3 + include/m_common_data.h | 6 +- include/m_demo.h | 152 ++++- include/m_event.h | 2 +- include/m_msg.h | 16 + include/m_player_lib.h | 14 + rel/ac_toudai_move.c_inc | 2 +- rel/m_demo.c | 1191 ++++++++++++++++++++++++++++++++++++++ 11 files changed, 1377 insertions(+), 18 deletions(-) create mode 100644 rel/m_demo.c diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 67ae9ba7..690cae09 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -74,6 +74,11 @@ m_debug_mode.c: .rodata: [0x80641D90, 0x80641DA8] .data: [0x80651358, 0x80651788] .bss: [0x81294010, 0x81294E18] +m_demo.c: + .text: [0x803984B4, 0x8039A540] + .rodata: [0x80641DA8, 0x80641F00] + .data: [0x80651788, 0x80651918] + .bss: [0x81294E18, 0x81295150] m_eappli.c: .text: [0x8039A5E0, 0x8039A960] .bss: [0x81295150, 0x81295550] diff --git a/include/MSL_C/math.h b/include/MSL_C/math.h index 93370922..01e4da80 100644 --- a/include/MSL_C/math.h +++ b/include/MSL_C/math.h @@ -11,6 +11,9 @@ extern "C" { #define PI 3.14159265358979323846 #define F_PI ((f32)PI) +#define SQRT2 (1.4142135623730950488016887242097) +#define F_SQRT2 ((f32)SQRT2) + #define SQRTF(f) (__frsqrte(f)) extern double sin(double deg); diff --git a/include/m_actor.h b/include/m_actor.h index f8c90101..9f77ec32 100644 --- a/include/m_actor.h +++ b/include/m_actor.h @@ -33,6 +33,7 @@ typedef void (*mActor_proc)(ACTOR*, GAME*); #define ACTOR_STATE_25 (1 << 25) #define ACTOR_STATE_26 (1 << 26) #define ACTOR_STATE_CAN_MOVE_IN_DEMO_SCENES (1 << 29) +#define ACTOR_STATE_IN_DEMO (1 << 30) //TODO: Name the unique ones for their correspondant actor diff --git a/include/m_bgm.h b/include/m_bgm.h index c27703d8..3c0ef18e 100644 --- a/include/m_bgm.h +++ b/include/m_bgm.h @@ -18,6 +18,9 @@ extern void mBGMPsComp_museum_status(int museum_status); extern void mBGMPsComp_make_ps_quietField(u16 stop_type); extern void mBGMPsComp_delete_ps_quietField(); extern void mBGMPsComp_make_ps_co_quiet(u16 stop_type, s16 frames); +extern void mBGMPsComp_volume_talk_start(); +extern void mBGMPsComp_volume_talk_end(); +extern void mBGMForce_inform_end(); #ifdef __cplusplus } diff --git a/include/m_common_data.h b/include/m_common_data.h index 93d7505e..e3c2a622 100644 --- a/include/m_common_data.h +++ b/include/m_common_data.h @@ -32,6 +32,7 @@ #include "m_all_grow.h" #include "m_fishrecord.h" #include "m_card.h" +#include "m_demo.h" #ifdef __cplusplus extern "C" { @@ -223,7 +224,8 @@ typedef struct common_data_s { /* 0x02852E */ s16 goods_power; /* 0x028530 */ Door_data_c door_data; /* misc door data */ /* 0x028544 */ Door_data_c structure_exit_door_data; /* door data for when exiting a building */ - /* 0x028558 */ u8 _28558[0x02857C - 0x028558]; + /* 0x028558 */ mDemo_Request_c start_demo_request; + /* 0x028568 */ Door_data_c event_door_data; /* 0x02857C */ Door_data_c famicom_emu_exit_door_data; /* 0x028590 */ u8 remove_cut_tree_info_bitfield; /* resets the cut tree states for trees in a visible acre */ /* 0x028591 */ u8 floor_idx; @@ -234,7 +236,7 @@ typedef struct common_data_s { /* 0x0285C0 */ s8 player_decoy_flag; /* 0x0285C1 */ u8 _285C1; /* 0x0285C2 */ u8 make_npc2_actor; - /* 0x0285C3 */ u8 _285C3[0x0285C6 - 0x0285C3]; + /* 0x0285C4 */ s16 event_id; /* 0x0285C6 */ u8 event_title_flags; /* 0x0285C7 */ u8 event_title_fade_in_progress; /* 0x0285C8 */ mEv_common_data_c event_common; diff --git a/include/m_demo.h b/include/m_demo.h index d1773f66..d4775428 100644 --- a/include/m_demo.h +++ b/include/m_demo.h @@ -3,11 +3,49 @@ #include "types.h" #include "m_actor_type.h" +#include "m_play_h.h" +#include "m_lib.h" +#include "m_scene.h" #ifdef __cplusplus extern "C" { #endif +#define mDemo_ORDER_VALUE_NUM 16 +#define mDemo_ORDER_VALUE_MAX 10 +#define mDemo_REQUEST_NUM 32 + +#define mDemo_MSG_PRIORITY 5 +#define mDemo_CAMERA_PRIORITY 6 + +#define mDemo_WINDOW_COLOR_R 235 +#define mDemo_WINDOW_COLOR_G 255 +#define mDemo_WINDOW_COLOR_B 235 +#define mDemo_WINDOW_COLOR_A 255 + +enum { + mDemo_STATE_WAIT, + mDemo_STATE_READY, + mDemo_STATE_RUN, + // ??? + mDemo_STATE_STOP = 9, + + mDemo_STATE_NUM +}; + +enum { + mDemo_DIRECT_N, + mDemo_DIRECT_NE, + mDemo_DIRECT_E, + mDemo_DIRECT_SE, + mDemo_DIRECT_S, + mDemo_DIRECT_SW, + mDemo_DIRECT_W, + mDemo_DIRECT_NW, + + mDemo_DIRECT_NUM +}; + enum demo_type { mDemo_TYPE_NONE, mDemo_TYPE_SCROLL, @@ -60,24 +98,110 @@ enum demo_clip_type { mDemo_CLIP_TYPE_NUM }; -extern void mDemo_Init(GAME_PLAY*); -extern void mDemo_Main(GAME_PLAY*); -extern int mDemo_Request(int type, ACTOR* actor, mDemo_REQUEST_PROC request_proc); -extern void mDemo_Set_msg_num(int msg_num); -extern int mDemo_Check(int type, ACTOR* actor); -extern int mDemo_Check_DiffAngle_forTalk(s16 angle); -extern int mDemo_Check_ListenAble(); -extern void mDemo_Set_ListenAble(); +typedef struct demo_req_s { + ACTOR* actor; + int type; + mDemo_REQUEST_PROC proc; + f32 talk_weight; +} mDemo_Request_c; + +typedef struct demo_door_data_s { + int type; + + struct { + f32 size; + int direct; + } house_info; +} mDemo_door_data_c; + +typedef struct demo_emsg_data_s { + int msg_no; + rgba_t window_color; + int msg_delay_timer; + int scene_delay_timer; + Door_data_c door_data; + u8 _24[4]; // unused? +} mDemo_emsg_data_c; + +typedef struct demo_talk_data_s { + int msg_no; + int turn; + int use_zoom_sound; + int display_name; + int change_player; + int return_get_golden_axe_demo; + int return_demo_wait; + rgba_t window_color; + u8 actor_saved_weight; +} mDemo_talk_data_c; + +typedef struct demo_data_s { + ACTOR* speaker_actor; + ACTOR* listen_actor; + int speaker_able; + int listen_able; + u16 order_data[mDemo_ORDER_NUM][mDemo_ORDER_VALUE_MAX]; + s8 change_player_destiny; + int state; + mDemo_Request_c current; + mDemo_Request_c request[mDemo_REQUEST_NUM]; + int request_num; + int priority_type; + int camera_type; + int keep_camera_type; + + union { + mDemo_door_data_c door; + mDemo_emsg_data_c emsg; + mDemo_talk_data_c talk; + } data; + + mDemo_Request_c request_save; +} mDemo_Data_c; + extern ACTOR* mDemo_Get_talk_actor(); +extern void mDemo_Set_speaker_actor(ACTOR* actor); extern void mDemo_Set_OrderValue(int type, int idx, u16 value); extern u16 mDemo_Get_OrderValue(int type, int idx); -extern void mDemo_Set_talk_return_demo_wait(u8 value); -extern void mDemo_Set_talk_turn(u8 value); -extern void mDemo_Set_talk_display_name(u8 value); -extern void mDemo_Set_camera(u8 value); -extern void mDemo_Set_talk_window_color(rgba_t* color); -extern int mDemo_CheckDemo(); +extern void mDemo_Set_msg_num(int msg_num); +extern int mDemo_Get_Talk_Actors(ACTOR** speaker, ACTOR** listener); +extern void mDemo_Set_change_player_destiny(s8 destiny); +extern void mDemo_Set_use_zoom_sound(u8 use_zoom_sound); +extern int mDemo_Get_use_zoom_sound(); +extern void mDemo_Set_talk_display_name(s8 display_name); +extern int mDemo_Get_talk_display_name(); +extern void mDemo_Set_talk_change_player(u8 change_player); +extern int mDemo_Get_talk_change_player(); +extern void mDemo_Set_talk_return_demo_wait(u8 return_demo_wait); +extern int mDemo_Get_talk_return_demo_wait(); +extern void mDemo_Set_talk_return_get_golden_axe_demo(u8 return_get_golden_axe_demo); +extern int mDemo_Get_talk_return_get_golden_axe_demo(); +extern void mDemo_Set_talk_turn(u8 turn); +extern int mDemo_Get_talk_turn(); +extern void mDemo_Set_talk_window_color(rgba_t* window_color); +extern rgba_t* mDemo_Get_talk_window_color_p(); +extern void mDemo_Set_camera(u8 camera_type); +extern int mDemo_Get_camera(); +extern int mDemo_CheckDemoType(); +extern int mDemo_Set_house_info(f32 size, int direct); extern void mDemo_stock_clear(); +extern int mDemo_Request(int type, ACTOR* actor, mDemo_REQUEST_PROC req_proc); +extern int mDemo_Check(int type, ACTOR* actor); +extern int mDemo_Start(ACTOR* actor); +extern int mDemo_Check_and_Go(int type, ACTOR* actor); +extern int mDemo_End(ACTOR* actor); +extern void mDemo_Main(GAME_PLAY* play); +extern void mDemo_Init(GAME_PLAY* play); +extern int mDemo_CheckDemo(); +extern int mDemo_CheckDemo4Event(); +extern void mDemo_Set_SpeakerAble(); +extern void mDemo_Set_ListenAble(); +extern void mDemo_Unset_SpeakerAble(); +extern void mDemo_Unset_ListenAble(); +extern int mDemo_Check_SpeakerAble(); +extern int mDemo_Check_ListenAble(); +extern int mDemo_Check_DiffAngle_forTalk(s16 diff_angle); +extern void mDemo_KeepCamera(int camera_type); #ifdef __cplusplus } diff --git a/include/m_event.h b/include/m_event.h index e7c69c49..4b08e778 100644 --- a/include/m_event.h +++ b/include/m_event.h @@ -171,7 +171,7 @@ enum event_table { mEv_EVENT_SPORTS_FAIR_AEROBICS, mEv_EVENT_SPORTS_FAIR_TUG_OF_WAR, mEv_EVENT_SPORTS_FAIR_FOOT_RACE, - mEv_EVENT_SPRING_SPORTS_FAIR, + mEv_EVENT_SPORTS_FAIR, mEv_EVENT_APRILFOOLS_DAY, mEv_EVENT_RUMOR_APRILFOOLS_DAY, mEv_EVENT_RUMOR_CHERRY_BLOSSOM_FESTIVAL, diff --git a/include/m_msg.h b/include/m_msg.h index 1df650d6..7fa863d9 100644 --- a/include/m_msg.h +++ b/include/m_msg.h @@ -13,6 +13,19 @@ extern "C" { #define mMsg_FREE_STRING_LEN 16 #define mMsg_MAIL_STRING_LEN 132 +enum { + mMsg_INDEX_HIDE, + mMsg_INDEX_APPEAR, + mMsg_INDEX_NORMAL, + mMsg_INDEX_CURSOL, + mMsg_INDEX_DISAPPEAR, + mMsg_INDEX_APPEAR_WAIT, + mMsg_INDEX_WAIT, + mMsg_INDEX_DISAPPEAR_WAIT, + + mMsg_INDEX_NUM +}; + enum { mMsg_FREE_STR0, mMsg_FREE_STR1, @@ -243,6 +256,9 @@ extern void mMsg_Get_BodyParam(u32 table_rom_start, u32 data_rom_start, int entr extern void mMsg_Set_LockContinue(mMsg_Window_c* msg_win); extern void mMsg_Unset_LockContinue(mMsg_Window_c* msg_win); extern int mMsg_Get_msg_num(mMsg_Window_c* msg_win); +extern int mMsg_Check_main_index(mMsg_Window_c* msg_win, int index); +extern int mMsg_request_main_appear(mMsg_Window_c* msg_win, ACTOR* other_actor, int display_name, rgba_t* window_color_p, int msg_no, int request_priority); +extern int mMsg_Check_main_hide(mMsg_Window_c* msg_win); #ifdef __cplusplus } diff --git a/include/m_player_lib.h b/include/m_player_lib.h index 99ffc66c..2682d280 100644 --- a/include/m_player_lib.h +++ b/include/m_player_lib.h @@ -28,6 +28,20 @@ extern int mPlib_Get_address_able_display(); extern int mPlib_get_player_actor_main_index(GAME_PLAY* play); extern int mPlib_check_player_actor_main_index_AllWade(GAME_PLAY* play); extern int mPlib_request_main_demo_wait_type1(GAME_PLAY* play, int param_2, void* param_3); +extern int mPlib_request_main_talk_type1(GAME_PLAY* play, ACTOR* other_actor, int turn, int flag); +extern int mPlib_request_main_talk_end_type1(GAME_PLAY* play, int return_demo_wait, int return_get_golden_axe_demo); +extern int mPlib_request_main_door_type1(GAME* game, const xyz_t* pos, s16 angle_y, int door_type, void* door_label); +extern int mPlib_request_main_door_type2(GAME* game, const xyz_t* pos, s16 angle_y, int door_type, void* door_label); +extern int mPlib_strength_request_main_door_priority(GAME* game); +extern int mPlib_check_request_main_wade_priority(GAME* game); +extern int mPlib_check_request_main_demo_wade_priority(GAME* game); +extern int mPlib_check_request_main_demo_geton_boat_wade_priority(GAME* game); +extern int mPlib_check_request_main_door_type1_priority(GAME* game); +extern int mPlib_check_request_main_door_type2_priority(GAME* game); +extern int mPlib_check_request_main_outdoor_priority(GAME* game); +extern int mPlib_check_request_main_talk_type1_priority(GAME* game); +extern int mPlib_check_request_main_speak_type1_priority(GAME* game); +extern int mPlib_Check_able_force_speak_label(GAME* game); extern void mPlib_Object_Exchange_keep_new_PlayerMdl(GAME_PLAY* play); extern void mPlib_Object_Exchange_keep_new_PlayerTex(GAME_PLAY* play, int bank_id, int base_idx); diff --git a/rel/ac_toudai_move.c_inc b/rel/ac_toudai_move.c_inc index b774ee31..9947de8d 100644 --- a/rel/ac_toudai_move.c_inc +++ b/rel/ac_toudai_move.c_inc @@ -192,7 +192,7 @@ static void aTOU_actor_move(ACTOR* actor, GAME* game){ pos.x = light->actor_class.world.position.x; pos.y = light->actor_class.world.position.y; pos.z = light->actor_class.world.position.z - 60.0f; - mPlib_request_main_door_type1(play, &pos, 0, 1, light); + mPlib_request_main_door_type1(game, &pos, 0, 1, light); } } aTOU_color_ctrl(light); diff --git a/rel/m_demo.c b/rel/m_demo.c new file mode 100644 index 00000000..e18553b7 --- /dev/null +++ b/rel/m_demo.c @@ -0,0 +1,1191 @@ +#include "m_demo.h" + +#include "m_common_data.h" +#include "m_player_lib.h" +#include "m_choice.h" +#include "m_msg.h" +#include "m_bgm.h" +#include "m_event.h" +#include "_mem.h" + +/* Z-X */ +static f32 direct_vector[mDemo_DIRECT_NUM][2] = { + { -1.0f, 0.0f }, + { -F_SQRT2, F_SQRT2 }, + { 0.0f, 1.0f }, + { F_SQRT2, F_SQRT2 }, + { 1.0f, 0.0f }, + { F_SQRT2, -F_SQRT2 }, + { 0.0f, -1.0f }, + { -F_SQRT2, -F_SQRT2 } +}; + +static s16 direct_back_angle[mDemo_DIRECT_NUM] = { + 0x0000, + 0xE000, + 0xC000, + 0xA000, + 0x8000, + 0x6000, + 0x4000, + 0x2000 +}; + +static mDemo_Data_c demo_data; +static mDemo_Data_c* const demo = &demo_data; + +static int mDemo_Check_talk_type() { + int res = FALSE; + + switch (demo->current.type) { + case mDemo_TYPE_TALK: + case mDemo_TYPE_SPEAK: + case mDemo_TYPE_REPORT: + case mDemo_TYPE_SPEECH: + res = TRUE; + break; + } + + return res; +} + +extern ACTOR* mDemo_Get_talk_actor() { + if (mDemo_Check_talk_type() == TRUE) { + return demo->current.actor; + } + + return NULL; +} + +/* @unused @fabricated */ +extern void mDemo_Set_speaker_actor(ACTOR* actor) { + demo->current.actor = actor; +} + +extern void mDemo_Set_OrderValue(int type, int idx, u16 value) { + if (type >= 0 && type < mDemo_ORDER_NUM && idx >= 0 && idx < mDemo_ORDER_VALUE_MAX) { + demo->order_data[type][idx] = value; + } +} + +extern u16 mDemo_Get_OrderValue(int type, int idx) { + if (type >= 0 && type < mDemo_ORDER_NUM && idx >= 0 && idx < mDemo_ORDER_VALUE_MAX) { + return demo->order_data[type][idx]; + } + + return 0; +} + +static void mDemo_Init_OrderValue() { + int i; + int j; + + for (i = 0; i < mDemo_ORDER_NUM; i++) { + for (j = 0; j < mDemo_ORDER_VALUE_MAX; j++) { + demo->order_data[i][j] = 0; + } + } +} + +extern void mDemo_Set_msg_num(int msg_num) { + if (mDemo_Check_talk_type() == TRUE) { + demo->data.talk.msg_no = msg_num; + } +} + +extern int mDemo_Get_Talk_Actors(ACTOR** speaker, ACTOR** listener) { + if (mDemo_Check_talk_type() == TRUE) { + + speaker[0] = demo->speaker_actor; + listener[0] = demo->listen_actor; + return TRUE; + } + else { + speaker[0] = NULL; + listener[0] = NULL; + return FALSE; + } +} + +extern void mDemo_Set_change_player_destiny(s8 destiny) { + demo->change_player_destiny = destiny; +} + +static int mDemo_Get_change_player_destiny() { + return demo->change_player_destiny; +} + +static void mDemo_Clear_change_player_destiny() { + mDemo_Set_change_player_destiny(-1); +} + +static void mDemo_Copy_change_player_destiny() { + if (mDemo_Get_change_player_destiny() >= 0) { + Private_c* priv = Common_Get(now_private); + lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time); + + priv->destiny.received_time.sec = rtc_time->sec; + priv->destiny.received_time.min = rtc_time->min; + priv->destiny.received_time.hour = rtc_time->hour; + priv->destiny.received_time.day = rtc_time->day; + priv->destiny.received_time.weekday = rtc_time->weekday; + priv->destiny.received_time.month = rtc_time->month; + priv->destiny.received_time.year = rtc_time->year; + priv->destiny.type = mDemo_Get_change_player_destiny(); + mDemo_Clear_change_player_destiny(); + } +} + +extern void mDemo_Set_use_zoom_sound(u8 use_zoom_sound) { + if (mDemo_Check_talk_type() == TRUE) { + demo->data.talk.use_zoom_sound = use_zoom_sound; + } +} + +extern int mDemo_Get_use_zoom_sound() { + if (mDemo_Check_talk_type() == TRUE) { + return demo->data.talk.use_zoom_sound; + } + + return FALSE; +} + +extern void mDemo_Set_talk_display_name(s8 display_name) { + if (mDemo_Check_talk_type() == TRUE) { + demo->data.talk.display_name = display_name; + } +} + +/* @unused @fabricated */ +extern int mDemo_Get_talk_display_name() { + if (mDemo_Check_talk_type() == TRUE) { + return demo->data.talk.display_name; + } + + return FALSE; +} + +extern void mDemo_Set_talk_change_player(u8 change_player) { + if (mDemo_Check_talk_type() == TRUE) { + demo->data.talk.change_player = change_player; + } +} + +/* @unused @fabricated */ +extern int mDemo_Get_talk_change_player() { + if (mDemo_Check_talk_type() == TRUE) { + return demo->data.talk.change_player; + } + + return FALSE; +} + +extern void mDemo_Set_talk_return_demo_wait(u8 return_demo_wait) { + if (mDemo_Check_talk_type() == TRUE) { + demo->data.talk.return_demo_wait = return_demo_wait; + } +} + +/* @unused @fabricated */ +extern int mDemo_Get_talk_return_demo_wait() { + if (mDemo_Check_talk_type() == TRUE) { + return demo->data.talk.return_demo_wait; + } + + return FALSE; +} + +extern void mDemo_Set_talk_return_get_golden_axe_demo(u8 return_get_golden_axe_demo) { + if (mDemo_Check_talk_type() == TRUE) { + demo->data.talk.return_get_golden_axe_demo = return_get_golden_axe_demo; + } +} + +/* @unused @fabricated */ +extern int mDemo_Get_talk_return_get_golden_axe_demo() { + if (mDemo_Check_talk_type() == TRUE) { + return demo->data.talk.return_get_golden_axe_demo; + } + + return FALSE; +} + +extern void mDemo_Set_talk_turn(u8 turn) { + if (mDemo_Check_talk_type() == TRUE) { + demo->data.talk.turn = turn; + } +} + +extern int mDemo_Get_talk_turn() { + if (mDemo_Check_talk_type() == TRUE) { + return demo->data.talk.turn; + } + + return FALSE; +} + +extern void mDemo_Set_talk_window_color(rgba_t* window_color) { + switch (demo->current.type) { + case mDemo_TYPE_TALK: + case mDemo_TYPE_SPEAK: + case mDemo_TYPE_REPORT: + case mDemo_TYPE_SPEECH: + demo->data.talk.window_color = *window_color; + break; + + case mDemo_TYPE_EVENTMSG: + case mDemo_TYPE_EVENTMSG2: + demo->data.emsg.window_color = *window_color; + break; + } +} + +/* @unused @fabricated */ +extern rgba_t* mDemo_Get_talk_window_color_p() { + if (demo->current.type >= mDemo_TYPE_TALK && demo->current.type < mDemo_TYPE_OUTDOOR) { + return &demo->data.talk.window_color; + } + else if (demo->current.type >= mDemo_TYPE_EVENTMSG && demo->current.type < mDemo_TYPE_15) { + return &demo->data.emsg.window_color; + } + + return NULL; +} + +extern void mDemo_Set_camera(u8 camera_type) { + demo->camera_type = camera_type; +} + +extern int mDemo_Get_camera() { + return demo->camera_type; +} + +extern int mDemo_CheckDemoType() { + if (mDemo_CheckDemo()) { + return demo->current.type; + } + + return mDemo_TYPE_NONE; +} + +static int change_camera(int camera_type) { + GAME_PLAY* play; + PLAYER_ACTOR* player; + + player = GET_PLAYER_ACTOR_NOW(); + play = (GAME_PLAY*)gamePT; + + if (camera_type == play->camera.now_main_index) { + return FALSE; + } + + switch (camera_type) { + case CAMERA2_PROCESS_TALK: + Camera2_request_main_talk(play, (ACTOR*)player, demo->current.actor, mDemo_CAMERA_PRIORITY); + break; + case CAMERA2_PROCESS_ITEM: + Camera2_request_main_item(play, 0, mDemo_CAMERA_PRIORITY); + break; + case CAMERA2_PROCESS_DOOR: + Camera2_request_main_door(play, (ACTOR*)player, demo->current.type != mDemo_TYPE_OUTDOOR, mDemo_CAMERA_PRIORITY); + break; + case CAMERA2_PROCESS_LOCK: + { + s_xyz angle; + f32 dist; + int sh_bx; + int sh_bz; + xyz_t camera_wpos; + + switch (demo->current.type) { + case mDemo_TYPE_EVENTMSG: + { + Camera2_main_Simple_AngleDistStd(play, &angle, &dist); + Camera2_request_main_simple((GAME_PLAY*)gamePT, &player->actor_class.world.position, &angle, dist, 0, mDemo_CAMERA_PRIORITY); + break; + } + + case mDemo_TYPE_SPEECH: + case mDemo_TYPE_EVENTMSG2: + { + Camera2_main_Simple_AngleDistStd(play, &angle, &dist); + mFI_BlockKind2BkNum(&sh_bx, &sh_bz, mRF_BLOCKKIND_SHRINE); + mFI_BkNum2WposXZ(&camera_wpos.x, &camera_wpos.z, sh_bx, sh_bz); + camera_wpos.x += 320.0f; + camera_wpos.y = player->actor_class.world.position.y; + camera_wpos.z += 400.0f; + Camera2_request_main_simple((GAME_PLAY*)gamePT, &camera_wpos, &angle, dist, 0, mDemo_CAMERA_PRIORITY); + break; + } + } + + break; + } + case CAMERA2_PROCESS_CUST_TALK: + { + switch (demo->current.actor->id) { + case mAc_PROFILE_EV_YOMISE: + Camera2_request_main_listen_front_low_talk(play, (ACTOR*)player, demo->current.actor, mDemo_CAMERA_PRIORITY); + break; + } + + break; + } + case CAMERA2_PROCESS_SIMPLE: + { + switch (demo->current.actor->id) { + case mAc_PROFILE_EV_DESIGNER: + Camera2_request_main_simple_kirin(play, &demo->current.actor->world.position, mDemo_CAMERA_PRIORITY - 1); + break; + } + + break; + } + case CAMERA2_PROCESS_NORMAL: + Camera2_request_main_normal(play, 0, mDemo_CAMERA_PRIORITY - 1); + break; + case CAMERA2_PROCESS_INTER2: + { + xyz_t center; + xyz_t eye; + + center = play->camera.lookat.center; + center.x -= 80.0f; + + eye = play->camera.lookat.eye; + eye.x -= 80.0f; + eye.z -= 20.0f; + + Camera2_request_main_inter(play, ¢er, &eye, ¢er, &eye, 0.6f, 0.3f, TRUE, 14, mDemo_CAMERA_PRIORITY + 1); + play->camera.requested_main_index = CAMERA2_PROCESS_INTER2; + break; + } + case CAMERA2_PROCESS_NUM: + break; + } + + return TRUE; +} + +static int set_speak_default() { + PLAYER_ACTOR* player; + + demo->data.talk.msg_no = 0; + demo->data.talk.turn = FALSE; + demo->data.talk.display_name = TRUE; + demo->data.talk.change_player = TRUE; + demo->data.talk.return_demo_wait = FALSE; + demo->data.talk.return_get_golden_axe_demo = FALSE; + demo->data.talk.use_zoom_sound = TRUE; + demo->data.talk.window_color.r = mDemo_WINDOW_COLOR_R; + demo->data.talk.window_color.g = mDemo_WINDOW_COLOR_G; + demo->data.talk.window_color.b = mDemo_WINDOW_COLOR_B; + demo->data.talk.window_color.a = mDemo_WINDOW_COLOR_A; + demo->camera_type = CAMERA2_PROCESS_TALK; + mDemo_Unset_SpeakerAble(); + mDemo_Unset_ListenAble(); + + player = GET_PLAYER_ACTOR_NOW(); + demo->speaker_actor = (ACTOR*)player; + demo->listen_actor = demo->current.actor; + return TRUE; +} + +static int set_report_default() { + PLAYER_ACTOR* player; + + demo->data.talk.msg_no = 0; + demo->data.talk.turn = FALSE; + demo->data.talk.display_name = FALSE; + demo->data.talk.change_player = FALSE; + demo->data.talk.return_demo_wait = FALSE; + demo->data.talk.return_get_golden_axe_demo = FALSE; + demo->data.talk.use_zoom_sound = TRUE; + demo->data.talk.window_color.r = mDemo_WINDOW_COLOR_R; + demo->data.talk.window_color.g = mDemo_WINDOW_COLOR_G; + demo->data.talk.window_color.b = mDemo_WINDOW_COLOR_B; + demo->data.talk.window_color.a = mDemo_WINDOW_COLOR_A; + demo->camera_type = CAMERA2_PROCESS_NORMAL; + mDemo_Set_SpeakerAble(); + mDemo_Unset_ListenAble(); + player = GET_PLAYER_ACTOR_NOW(); + demo->speaker_actor = (ACTOR*)player; + demo->listen_actor = demo->current.actor; + return TRUE; +} + +static int set_talk_default() { + demo->data.talk.msg_no = 0; + demo->data.talk.turn = TRUE; + demo->data.talk.display_name = TRUE; + demo->data.talk.change_player = TRUE; + demo->data.talk.return_demo_wait = FALSE; + demo->data.talk.return_get_golden_axe_demo = FALSE; + demo->data.talk.use_zoom_sound = TRUE; + demo->data.talk.window_color.r = mDemo_WINDOW_COLOR_R; + demo->data.talk.window_color.g = mDemo_WINDOW_COLOR_G; + demo->data.talk.window_color.b = mDemo_WINDOW_COLOR_B; + demo->data.talk.window_color.a = mDemo_WINDOW_COLOR_A; + demo->camera_type = CAMERA2_PROCESS_TALK; + mDemo_Unset_SpeakerAble(); + mDemo_Unset_ListenAble(); + demo->speaker_actor = (ACTOR*)GET_PLAYER_ACTOR_NOW(); + demo->listen_actor = demo->current.actor; + return TRUE; +} + +static int wait_talk_start() { + PLAYER_ACTOR* player = GET_PLAYER_ACTOR_NOW(); + + if (demo->data.talk.change_player) { + if ( + mPlib_get_player_actor_main_index((GAME_PLAY*)gamePT) != 65 && + mPlib_request_main_talk_type1((GAME_PLAY*)gamePT, demo->current.actor, demo->data.talk.turn, FALSE) == FALSE + ) { + return FALSE; + } + } + else { + mDemo_Set_SpeakerAble(); + } + + if (mDemo_Check_SpeakerAble() && mDemo_Check_ListenAble()) { + mMsg_Window_c* msg_win = mMsg_Get_base_window_p(); + + mDemo_Init_OrderValue(); + + if (mMsg_Check_main_index(msg_win, mMsg_INDEX_APPEAR) == FALSE) { + int msg_no = demo->data.talk.msg_no; // pulled out here, probably for debug or something? + + player->actor_class.state_bitfield |= ACTOR_STATE_IN_DEMO; + demo->current.actor->state_bitfield |= ACTOR_STATE_IN_DEMO; + demo->data.talk.actor_saved_weight = demo->current.actor->status_data.weight; + demo->current.actor->status_data.weight = 255; + mMsg_request_main_appear(msg_win, demo->current.actor, demo->data.talk.display_name, &demo->data.talk.window_color, msg_no, mDemo_MSG_PRIORITY); + + if (demo->data.talk.use_zoom_sound) { + sAdo_SysTrgStart(demo->camera_type == CAMERA2_PROCESS_TALK ? (u16)0x8014 : (u16)0x8004); + } + + if ( + mFI_GET_TYPE(mFI_GetFieldId()) != mFI_FIELD_DEMO_STARTDEMO && + demo->data.talk.msg_no != 0x07DD && /* Porter "Now arriving at !" message (new player) */ + demo->data.talk.msg_no != 0x0949 && /* Porter "Now arriving in !" message (returning home) */ + demo->data.talk.msg_no != 0x0965 && /* Porter "Take care!" message (travelling to another town) */ + demo->data.talk.msg_no != 0x07DE /* Tom Nook "Hey, you there!" message (walking down from station) */ + ) { + mBGMPsComp_volume_talk_start(); + } + + return TRUE; + } + } + + return FALSE; +} + +static int wait_talk_end() { + if (mMsg_Check_main_hide(mMsg_Get_base_window_p()) || demo->state == mDemo_STATE_STOP) { + if (demo->data.talk.change_player) { + mPlib_request_main_talk_end_type1((GAME_PLAY*)gamePT, demo->data.talk.return_demo_wait, demo->data.talk.return_get_golden_axe_demo); + } + + demo->current.actor->status_data.weight = demo->data.talk.actor_saved_weight; + mDemo_Copy_change_player_destiny(); + + if (mFI_GET_TYPE(mFI_GetFieldId()) != mFI_FIELD_DEMO_STARTDEMO) { + mBGMPsComp_volume_talk_end(); + } + + return TRUE; + } + + return FALSE; +} + +static int set_speech_default() { + demo->data.talk.msg_no = 0; + demo->data.talk.turn = FALSE; + demo->data.talk.display_name = TRUE; + demo->data.talk.change_player = FALSE; + demo->data.talk.return_demo_wait = FALSE; + demo->data.talk.return_get_golden_axe_demo = FALSE; + demo->data.talk.use_zoom_sound = TRUE; + demo->data.talk.window_color.r = mDemo_WINDOW_COLOR_R; + demo->data.talk.window_color.g = mDemo_WINDOW_COLOR_G; + demo->data.talk.window_color.b = mDemo_WINDOW_COLOR_B; + demo->data.talk.window_color.a = mDemo_WINDOW_COLOR_A; + demo->camera_type = CAMERA2_PROCESS_INTER2; + mDemo_Set_SpeakerAble(); + mDemo_Unset_ListenAble(); + demo->speaker_actor = (ACTOR*)GET_PLAYER_ACTOR_NOW(); + demo->listen_actor = demo->current.actor; + return TRUE; +} + +static int wait_scroll_start() { + return TRUE; +} + +static int set_door_default() { + demo->data.door.type = 0; + demo->data.door.house_info.size = 80.0f; + demo->data.door.house_info.direct = mDemo_DIRECT_S; + demo->camera_type = CAMERA2_PROCESS_NORMAL; + return TRUE; +} + +static int wait_door_start() { + PLAYER_ACTOR* player = GET_PLAYER_ACTOR_NOW(); + ACTOR* door_actor = (ACTOR*)(*GET_PLAYER_ACTOR_NOW()->get_door_label_proc)(gamePT); + + if (demo->current.actor == door_actor) { + return TRUE; + } + else { + f32 size_adj = demo->data.door.house_info.size / 2.0f + 20.0f; + xyz_t pos; + s16 back_angle; + + pos.x = demo->current.actor->world.position.x + size_adj * direct_vector[demo->data.door.house_info.direct][1]; + pos.y = demo->current.actor->world.position.y; + pos.z = demo->current.actor->world.position.z + size_adj * direct_vector[demo->data.door.house_info.direct][0]; + + back_angle = direct_back_angle[demo->data.door.house_info.direct]; + player->actor_class.state_bitfield |= ACTOR_STATE_IN_DEMO; + demo->current.actor->state_bitfield |= ACTOR_STATE_IN_DEMO; + + mPlib_request_main_door_type1(gamePT, &pos, back_angle, demo->data.door.type, demo->current.actor); + mPlib_strength_request_main_door_priority(gamePT); + } + + return FALSE; +} + +extern int mDemo_Set_house_info(f32 size, int direct) { + if (demo->current.type == mDemo_TYPE_DOOR || demo->current.type == mDemo_TYPE_DOOR2) { + demo->data.door.house_info.size = size; + demo->data.door.house_info.direct = direct; + return TRUE; + } + + return FALSE; +} + +static int wait_door2_start() { + PLAYER_ACTOR* player = GET_PLAYER_ACTOR_NOW(); + ACTOR* door_actor = (ACTOR*)(*GET_PLAYER_ACTOR_NOW()->get_door_label_proc)(gamePT); + + if (demo->current.actor == door_actor) { + return TRUE; + } + else { + f32 size_adj = demo->data.door.house_info.size / 2.0f + 20.0f; + xyz_t pos; + s16 back_angle; + + pos.x = demo->current.actor->world.position.x + size_adj * direct_vector[demo->data.door.house_info.direct][1]; + pos.y = demo->current.actor->world.position.y; + pos.z = demo->current.actor->world.position.z + size_adj * direct_vector[demo->data.door.house_info.direct][0]; + + back_angle = direct_back_angle[demo->data.door.house_info.direct]; + player->actor_class.state_bitfield |= ACTOR_STATE_IN_DEMO; + demo->current.actor->state_bitfield |= ACTOR_STATE_IN_DEMO; + + mPlib_request_main_door_type2(gamePT, &pos, back_angle, demo->data.door.type, demo->current.actor); + mPlib_strength_request_main_door_priority(gamePT); + } + + return FALSE; +} + +static s16 get_title_no_for_event(s16 event) { + switch (event) { + case mEv_EVENT_FIREWORKS_SHOW: + return 0; + case mEv_EVENT_CHERRY_BLOSSOM_FESTIVAL: + return 1; + case mEv_EVENT_SPORTS_FAIR_AEROBICS: + return 2; + case mEv_EVENT_SPORTS_FAIR_FOOT_RACE: + return 3; + case mEv_EVENT_SPORTS_FAIR_BALL_TOSS: + return 4; + case mEv_EVENT_SPORTS_FAIR_TUG_OF_WAR: + return 5; + case mEv_EVENT_MORNING_AEROBICS: + return 6; + case mEv_EVENT_HARVEST_MOON_FESTIVAL: + return 7; + case mEv_EVENT_METEOR_SHOWER: + return 8; + case mEv_EVENT_NEW_YEARS_EVE_COUNTDOWN: + return 9; + case mEv_EVENT_NEW_YEARS_DAY: + return 10; + case mEv_EVENT_FISHING_TOURNEY_1: + case mEv_EVENT_FISHING_TOURNEY_2: + return 11; + case mEv_EVENT_HALLOWEEN: + return 12; + case mEv_EVENT_TOY_DAY_JINGLE: + return 13; + case mEv_EVENT_SPORTS_FAIR: + return 10; + case mEv_EVENT_GROUNDHOG_DAY: + return 14; + case mEv_EVENT_HARVEST_FESTIVAL: + return 15; + default: + return -1; + } +} + +static int set_emsg_default() { + s16 event_id = Common_Get(event_id); + s16 flags = Common_Get(event_title_flags); + s16 title_no; + + memcpy(&demo->data.emsg.door_data, Common_GetPointer(event_door_data), sizeof(Door_data_c)); + title_no = get_title_no_for_event(event_id); + + if (title_no >= 0) { + if (flags == 1) { + demo->data.emsg.msg_no = 0x1743; // start message + } + else { + demo->data.emsg.msg_no = 0x1799; // conclusion message + } + + demo->data.emsg.msg_no += title_no; + } + else { + demo->data.emsg.msg_no = 0; + } + + demo->data.emsg.window_color.r = mDemo_WINDOW_COLOR_R; + demo->data.emsg.window_color.g = mDemo_WINDOW_COLOR_G; + demo->data.emsg.window_color.b = mDemo_WINDOW_COLOR_B; + demo->data.emsg.window_color.a = mDemo_WINDOW_COLOR_A; + demo->camera_type = CAMERA2_PROCESS_LOCK; + demo->data.emsg.msg_delay_timer = 0; + demo->data.emsg.scene_delay_timer = 30; + + return TRUE; +} + +static int wait_emsg_start() { + mMsg_Window_c* msg_win = mMsg_Get_base_window_p(); + + if (demo->data.emsg.msg_delay_timer <= 0) { + if (demo->data.emsg.msg_no != 0) { + mMsg_request_main_appear(msg_win, NULL, FALSE, &demo->data.emsg.window_color, demo->data.emsg.msg_no, mDemo_MSG_PRIORITY); + } + + Common_Set(event_title_flags, 2); + return TRUE; + } + else { + demo->data.emsg.msg_delay_timer--; + } + + return FALSE; +} + +static int wait_emsg_end() { + GAME_PLAY* play = (GAME_PLAY*)gamePT; + mMsg_Window_c* msg_win = mMsg_Get_base_window_p(); + + if (mMsg_Check_main_hide(msg_win)) { + demo->data.emsg.scene_delay_timer--; + } + + if (demo->data.emsg.scene_delay_timer <= 0 || demo->state == mDemo_STATE_STOP) { + if (goto_other_scene(play, &demo->data.emsg.door_data, FALSE)) { + play->fb_wipe_type = demo->data.emsg.door_data.wipe_type; + play->fb_fade_type = 11; + Common_Set(transition.wipe_type, demo->data.emsg.door_data.wipe_type); + mBGMForce_inform_end(); + + return TRUE; + } + else { + return FALSE; + } + } + + return FALSE; +} + +static int set_emsg2_default() { + memcpy(&demo->data.emsg.door_data, Common_GetPointer(event_door_data), sizeof(Door_data_c)); + demo->camera_type = CAMERA2_PROCESS_LOCK; + demo->data.emsg.msg_delay_timer = 0; + demo->data.emsg.scene_delay_timer = 30; + memcpy(&demo->request_save, &demo->current, sizeof(mDemo_Request_c)); + + return TRUE; +} + +static int wait_emsg2_start() { + Common_Set(event_title_flags, 2); + return TRUE; +} + +static int wait_emsg2_end() { + int res = FALSE; + + if (Common_Get(event_title_fade_in_progress) == TRUE) { + GAME_PLAY* play = (GAME_PLAY*)gamePT; + + if (goto_other_scene(play, Common_GetPointer(event_door_data), FALSE)) { + play->fb_wipe_type = Common_Get(event_door_data).wipe_type; + play->fb_fade_type = 11; + Common_Set(transition.wipe_type, Common_Get(event_door_data).wipe_type); + mBGMForce_inform_end(); + memset(&demo->request_save, 0, sizeof(mDemo_Request_c)); + + res = TRUE; + } + } + + return res; +} + +static f32 weight_of_talk_position(ACTOR* actor) { + PLAYER_ACTOR* player = GET_PLAYER_ACTOR_NOW(); + f32 actor_talk_dist; + f32 player_dist; + f32 dist_y = player->actor_class.world.position.y - actor->world.position.y; + s16 diff_y = player->actor_class.shape_info.rotation.y - actor->player_angle_y; + s16 angle_y; + + if (dist_y < 0.0f) { + dist_y = -dist_y; + } + + angle_y = diff_y < 0 ? (s16)(diff_y + -0x8000) : (s16)(-diff_y + -0x8000); + + if (actor->player_distance_xz <= actor->talk_distance && dist_y <= 33.0f && angle_y <= 12530) { + f32 dist_factor = 1.0f - (actor->player_distance_xz / 55.0f); + f32 angle_factor; + + dist_y = 1.0f - (actor->player_distance_xz / 55.0f); + + if (dist_y < 0.0f) { + dist_y = 0.0f; + } + + angle_factor = 1.0f - ((f32)((int)angle_y) / 12530.0f); + + return angle_factor * angle_factor * 0.6f + dist_y * dist_y * 0.4f; + } + else { + return -99.0f; + } +} + +static int allways_true() { + return TRUE; +} + +static int allways_false() { + return FALSE; +} + +static int scroll_check() { + return mPlib_check_request_main_wade_priority(gamePT); +} + +static int scroll2_check() { + return mPlib_check_request_main_demo_wade_priority(gamePT); +} + +static int scroll3_check() { + return mPlib_check_request_main_demo_geton_boat_wade_priority(gamePT); +} + +static int door_check() { + return mPlib_check_request_main_door_type1_priority(gamePT); +} + +static int door2_check() { + return mPlib_check_request_main_door_type2_priority(gamePT); +} + +static int outdoor_check() { + return mPlib_check_request_main_outdoor_priority(gamePT); +} + +static int talk_check() { + return mPlib_check_request_main_talk_type1_priority(gamePT) != 0; +} + +static int speak_check() { + return mPlib_check_request_main_speak_type1_priority(gamePT) != 0; +} + +typedef int (*mDemo_PROC)(); + +static int choice_demo_sub() { + static const mDemo_PROC check_func[mDemo_TYPE_NUM] = { + &allways_true, + &scroll_check, + &allways_true, + &door_check, + &allways_true, + &scroll2_check, + &door2_check, + &talk_check, + &speak_check, + &allways_true, + &allways_true, + &outdoor_check, + &allways_true, + &allways_true, + &allways_true, + &allways_true, + &scroll3_check + }; + + f32 max_talk_weight = 0.0f; + int i; + int idx = -1; + + for (i = 0; i < demo->request_num; i++) { + mDemo_Request_c* request = &demo->request[i]; + int type = request->type; + + if ( + ((mEv_CheckTitleDemo() == 0 || type == mDemo_TYPE_SCROLL || + (mEv_CheckTitleDemo() == -9 && type == mDemo_TYPE_SPEAK && + request->actor != NULL && request->actor->id == mAc_PROFILE_NPC_TOTAKEKE)) && + (demo->request_save.type != mDemo_TYPE_NONE || type >= demo->priority_type) + ) && (*check_func[type])() != FALSE + ) { + if (type == mDemo_TYPE_TALK) { + if (chkTrigger(BUTTON_A) && request->talk_weight > max_talk_weight) { + idx = i; + max_talk_weight = request->talk_weight; + } + } + else { + idx = i; /* non-TALK types have instant priority */ + break; + } + } + } + + return idx; +} + +static int choice_demo() { + static const mDemo_PROC default_set_func[mDemo_TYPE_NUM] = { + &allways_true, + &allways_true, + &allways_true, + &set_door_default, + &allways_true, + &allways_true, + &set_door_default, + &set_talk_default, + &set_speak_default, + &set_report_default, + &set_speech_default, + &allways_true, + &allways_true, + &set_emsg_default, + &set_emsg2_default, + &allways_true, + &allways_true + }; + + int request_idx = choice_demo_sub(); + + if (request_idx != -1) { + memcpy(&demo->current, &demo->request[request_idx], sizeof(mDemo_Request_c)); + (*default_set_func[demo->current.type])(); + + if (demo->current.proc != NULL) { + (*demo->current.proc)(demo->current.actor); + } + + demo->state = 1; + } + + return request_idx; +} + +static int check_speech_request() { + int request_idx = choice_demo_sub(); + int res = FALSE; + + if (request_idx != -1) { + mDemo_Request_c* request = &demo->request[request_idx]; + + if (request->type == mDemo_TYPE_SPEECH) { + res = TRUE; + } + } + + return res; +} + +static void emsg_set() { + static rgba_t win_color = { 175, 255, 255, 255 }; + + mDemo_Set_talk_window_color(&win_color); +} + +static void init_demo() { + int initial_demo_type = Common_Get(start_demo_request).type; + + memset(&demo->current, 0, sizeof(mDemo_Request_c)); + memset(&demo->request_save, 0, sizeof(mDemo_Request_c)); + demo->state = mDemo_STATE_WAIT; + demo->request_num = 0; + demo->priority_type = 0; + demo->camera_type = CAMERA2_PROCESS_NORMAL; + demo->keep_camera_type = CAMERA2_PROCESS_STOP; + + switch (initial_demo_type) { + case mDemo_TYPE_EVENTMSG: + case mDemo_TYPE_EVENTMSG2: + mDemo_Request(initial_demo_type, NULL, &emsg_set); + Common_Set(start_demo_request.type, mDemo_TYPE_NONE); + break; + } +} + +static const mDemo_PROC wait_start[mDemo_TYPE_NUM] = { + &allways_true, + &wait_scroll_start, + &allways_true, + &wait_door_start, + &allways_true, + &wait_scroll_start, + &wait_door2_start, + &wait_talk_start, + &wait_talk_start, + &wait_talk_start, + &wait_talk_start, + &allways_true, + &allways_true, + &wait_emsg_start, + &wait_emsg2_start, + &allways_true, + &wait_scroll_start +}; + +static const mDemo_PROC wait_end[mDemo_TYPE_NUM] = { + &allways_false, + &allways_false, + &allways_false, + &allways_false, + &allways_false, + &allways_false, + &allways_false, + &wait_talk_end, + &wait_talk_end, + &wait_talk_end, + &wait_talk_end, + &allways_false, + &allways_false, + &wait_emsg_end, + &wait_emsg2_end, + &allways_false, + &allways_false +}; + +static void run_demo() { + if (demo->state == mDemo_STATE_READY) { + if ((*wait_start[demo->current.type])()) { + change_camera(demo->camera_type); + demo->state = mDemo_STATE_RUN; + } + } + else if (demo->state == mDemo_STATE_RUN && (*wait_end[demo->current.type])()) { + demo->state = mDemo_STATE_STOP; + } +} + +static void main_proc() { + PLAYER_ACTOR* player = GET_PLAYER_ACTOR_NOW(); + + if (demo->state == mDemo_STATE_STOP) { + player->actor_class.state_bitfield &= ~ACTOR_STATE_IN_DEMO; + + if (demo->current.actor != NULL) { + demo->current.actor->state_bitfield &= ~ACTOR_STATE_IN_DEMO; + } + + demo->camera_type = CAMERA2_PROCESS_NORMAL; + if (demo->keep_camera_type != CAMERA2_PROCESS_STOP && demo->current.actor != NULL) { + change_camera(demo->keep_camera_type); + } + else { + change_camera(demo->camera_type); + } + + demo->keep_camera_type = CAMERA2_PROCESS_STOP; + memset(&demo->current, 0, sizeof(mDemo_Request_c)); + demo->state = mDemo_STATE_WAIT; + } + + if (demo->request_save.type != mDemo_TYPE_NONE && demo->request_save.type == demo->current.type && check_speech_request() == TRUE) { + demo->state = mDemo_STATE_WAIT; + } + + if (demo->state == mDemo_STATE_WAIT) { + choice_demo(); + } + + if (demo->state != mDemo_STATE_WAIT) { + run_demo(); + } + + if (demo->state == mDemo_STATE_STOP && demo->request_save.type != mDemo_TYPE_NONE && demo->request_save.type != demo->current.type) { + memcpy(&demo->current, &demo->request_save, sizeof(mDemo_Request_c)); + demo->state = mDemo_STATE_RUN; + change_camera(CAMERA2_PROCESS_NUM); + } +} + +extern void mDemo_stock_clear() { + demo->request_num = 0; + demo->priority_type = 0; +} + +extern int mDemo_Request(int type, ACTOR* actor, mDemo_REQUEST_PROC req_proc) { + f32 weight = 1.0f; + int request_num = demo->request_num; + + if (request_num < mDemo_REQUEST_NUM) { + if (type >= demo->priority_type) { + mDemo_Request_c* req = &demo->request[request_num]; + + if (type == mDemo_TYPE_TALK) { + weight = weight_of_talk_position(actor); + + if (weight < 0.0f) { + return FALSE; + } + } + else if (type == mDemo_TYPE_SPEAK && mPlib_Check_able_force_speak_label(gamePT) == FALSE) { + return FALSE; + } + + demo->priority_type = type; + + req->type = type; + req->actor = actor; + req->proc = req_proc; + req->talk_weight = weight; + + demo->request_num++; + } + + return TRUE; + } + + return FALSE; +} + +extern int mDemo_Check(int type, ACTOR* actor) { + if (type == demo->current.type && actor == demo->current.actor) { + return TRUE; + } + + return FALSE; +} + +extern int mDemo_Start(ACTOR* actor) { + return FALSE; +} + +/* @unused @fabricated */ +extern int mDemo_Check_and_Go(int type, ACTOR* actor) { + if (mDemo_Check(type, actor) == FALSE) { + return FALSE; + } + + return mDemo_Start(actor); +} + +extern int mDemo_End(ACTOR* actor) { + if (actor == demo->current.actor) { + demo->state = mDemo_STATE_STOP; + return TRUE; + } + + return FALSE; +} + +extern void mDemo_Main(GAME_PLAY* play) { + main_proc(); +} + +extern void mDemo_Init(GAME_PLAY* play) { + demo->speaker_actor = NULL; + demo->listen_actor = NULL; + mDemo_Unset_SpeakerAble(); + mDemo_Unset_ListenAble(); + mDemo_Init_OrderValue(); + mDemo_Clear_change_player_destiny(); + init_demo(); +} + +extern int mDemo_CheckDemo() { + return demo->state != mDemo_STATE_WAIT; +} + +extern int mDemo_CheckDemo4Event() { + + + switch (mDemo_CheckDemoType()) { + case mDemo_TYPE_NONE: + case mDemo_TYPE_EVENTMSG: + case mDemo_TYPE_EVENTMSG2: + return FALSE; + } + + return TRUE; +} + +extern void mDemo_Set_SpeakerAble() { + demo->speaker_able = TRUE; +} + +extern void mDemo_Set_ListenAble() { + demo->listen_able = TRUE; +} + +extern void mDemo_Unset_SpeakerAble() { + demo->speaker_able = FALSE; +} + +extern void mDemo_Unset_ListenAble() { + demo->listen_able = FALSE; +} + +extern int mDemo_Check_SpeakerAble() { + return demo->speaker_able; +} + +extern int mDemo_Check_ListenAble() { + return demo->listen_able; +} + +extern int mDemo_Check_DiffAngle_forTalk(s16 diff_angle) { + int res = FALSE; + + if (diff_angle > -5000 && diff_angle < 5000) { + res = TRUE; + } + + return res; +} + +extern void mDemo_KeepCamera(int camera_type) { + demo->keep_camera_type = camera_type; +}