Implement & link ac_ev_broker

This commit is contained in:
Cuyler36
2024-08-14 09:25:32 -04:00
parent 0598a764e6
commit 029a4664f5
6 changed files with 439 additions and 9 deletions
+4
View File
@@ -726,6 +726,10 @@ ac_aprilfool_control.c:
ac_groundhog_control.c:
.text: [0x805155C8, 0x80515C48]
.data: [0x8069FD88, 0x8069FDD0]
ac_ev_broker.c:
.text: [0x80519D4C, 0x8051A880]
.rodata: [0x80649160, 0x80649178]
.data: [0x806A0128, 0x806A01B0]
ac_ev_castaway.c:
.text: [0x8051CAC4, 0x8051CDCC]
.rodata: [0x806491B0, 0x806491B8]
+16 -1
View File
@@ -3,11 +3,27 @@
#include "types.h"
#include "m_actor.h"
#include "ac_npc.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ac_ev_broker EV_BROKER_ACTOR;
typedef void (*aEBRK_ACT_PROC)(EV_BROKER_ACTOR*);
/* sizeof(EV_BROKER_ACTOR) == 0x9AC */
struct ac_ev_broker {
/* 0x000 */ NPC_ACTOR npc_class;
/* 0x994 */ int action;
/* 0x998 */ int next_action;
/* 0x99C */ int action_step;
/* 0x9A0 */ aEBRK_ACT_PROC action_proc;
/* 0x9A4 */ ACTOR* tent_actor;
/* 0x9A8 */ u8 pl_talk_lock;
};
extern ACTOR_PROFILE Ev_Broker_Profile;
#ifdef __cplusplus
@@ -15,4 +31,3 @@ extern ACTOR_PROFILE Ev_Broker_Profile;
#endif
#endif
+9 -8
View File
@@ -252,15 +252,16 @@ typedef void (*aNPC_THINK_PROC)(NPC_ACTOR*, GAME_PLAY*, int);
#define aNPC_THINK_INTERRUPT_OBSTANCE (1 << 2)
#define aNPC_THINK_INTERRUPT_ENTRANCE (1 << 3)
/* sizeof(aNPC_think_info_c) == 0x18 */
typedef struct npc_think_info_s {
int idx;
u8 end_flag;
u8 force_call_flag;
u16 force_call_timer;
int force_call_msg_no;
u8 force_call_camera_type;
aNPC_THINK_PROC think_proc;
u32 interrupt_flags;
/* 0x00 */ int idx;
/* 0x04 */ u8 end_flag;
/* 0x05 */ u8 force_call_flag;
/* 0x06 */ u16 force_call_timer;
/* 0x08 */ int force_call_msg_no;
/* 0x0C */ u8 force_call_camera_type;
/* 0x10 */ aNPC_THINK_PROC think_proc;
/* 0x14 */ u32 interrupt_flags;
} aNPC_think_info_c;
typedef void (*aNPC_SCHEDULE_PROC)(NPC_ACTOR*, GAME_PLAY*, int);
+1
View File
@@ -21,6 +21,7 @@ extern int mPlib_check_able_change_camera_normal_index();
extern void mPlib_request_main_refuse_type1(GAME* game);
extern void mPlib_request_main_wait_type3(GAME* game);
extern void mPlib_Set_able_force_speak_label(ACTOR* actor);
extern void mPlib_Reset_able_force_speak_label(void);
extern int mPlib_request_main_demo_walk_type1(GAME* game, f32 goal_x, f32 goal_z, f32 speed, int flag);
extern void mPlib_Set_goal_player_demo_walk(f32 goal_x, f32 goal_z, f32 speed);
extern void mPlib_Set_able_hand_all_item_in_demo(s8 enable);
+106
View File
@@ -0,0 +1,106 @@
#include "ac_ev_broker.h"
#include "m_common_data.h"
#include "m_player_lib.h"
#include "m_msg.h"
enum {
aEBRK_ACTION_TALK_WAIT,
aEBRK_ACTION_TURN,
aEBRK_ACTION_ENTER,
aEBRK_ACTION_HIDE,
aEBRK_ACTION_NUM
};
static void aEBRK_actor_ct(ACTOR* actorx, GAME* game);
static void aEBRK_actor_dt(ACTOR* actorx, GAME* game);
static void aEBRK_actor_init(ACTOR* actorx, GAME* game);
static void aEBRK_actor_move(ACTOR* actorx, GAME* game);
static void aEBRK_actor_draw(ACTOR* actorx, GAME* game);
static void aEBRK_actor_save(ACTOR* actorx, GAME* game);
// clang-format off
ACTOR_PROFILE Ev_Broker_Profile = {
mAc_PROFILE_EV_BROKER,
ACTOR_PART_NPC,
ACTOR_STATE_NO_MOVE_WHILE_CULLED | ACTOR_STATE_NO_DRAW_WHILE_CULLED,
SP_NPC_BROKER,
ACTOR_OBJ_BANK_KEEP,
sizeof(EV_BROKER_ACTOR),
&aEBRK_actor_ct,
&aEBRK_actor_dt,
&aEBRK_actor_init,
mActor_NONE_PROC1,
&aEBRK_actor_save,
};
// clang-format on
static void aEBRK_talk_request(ACTOR* actorx, GAME* game);
static int aEBRK_talk_init(ACTOR* actorx, GAME* game);
static int aEBRK_talk_end_chk(ACTOR* actorx, GAME* game);
static void aEBRK_schedule_proc(NPC_ACTOR* npc_actorx, GAME_PLAY* play, int sched_type);
static int aEBRK_get_sell_item_sum(void);
static int aEBRK_check_start_around(ACTOR* actorx, GAME* game);
static void aEBRK_actor_ct(ACTOR* actorx, GAME* game) {
static aNPC_ct_data_c ct_data = {
&aEBRK_actor_move, &aEBRK_actor_draw, 5, &aEBRK_talk_request, &aEBRK_talk_init, &aEBRK_talk_end_chk,
};
EV_BROKER_ACTOR* broker = (EV_BROKER_ACTOR*)actorx;
if (Common_Get(clip).npc_clip->birth_check_proc(actorx, game) == TRUE) {
broker->npc_class.schedule.schedule_proc = &aEBRK_schedule_proc;
Common_Get(clip).npc_clip->ct_proc(actorx, game, &ct_data);
broker->npc_class.actor_class.status_data.weight = 254;
if (aEBRK_get_sell_item_sum() == 0 || aEBRK_check_start_around(actorx, game) == FALSE) {
broker->npc_class.talk_info.talk_request_proc = (aNPC_TALK_REQUEST_PROC)&none_proc1;
broker->next_action = aEBRK_ACTION_HIDE;
} else {
int hide_npc = Common_Get(special_event_common).broker.hide_npc;
broker->npc_class.condition_info.hide_request = hide_npc;
if (hide_npc == TRUE) {
broker->npc_class.talk_info.talk_request_proc = (aNPC_TALK_REQUEST_PROC)&none_proc1;
broker->next_action = aEBRK_ACTION_HIDE;
} else {
broker->next_action = aEBRK_ACTION_TALK_WAIT;
}
}
}
}
static void aEBRK_actor_save(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->save_proc(actorx, game);
}
static void aEBRK_actor_dt(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->dt_proc(actorx, game);
Common_Get(special_event_common).broker.hide_npc = FALSE;
mEv_actor_dying_message(mEv_EVENT_BROKER_SALE, actorx);
}
static void aEBRK_actor_init(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->init_proc(actorx, game);
}
static void aEBRK_set_animation(EV_BROKER_ACTOR* broker, int action) {
static int animeSeqNo[] = {
aNPC_ANIM_WAIT1,
aNPC_ANIM_WALK1,
aNPC_ANIM_WALK1,
aNPC_ANIM_WAIT1,
};
Common_Get(clip).npc_clip->animation_init_proc(&broker->npc_class.actor_class, animeSeqNo[action], FALSE);
}
static void aEBRK_actor_draw(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->draw_proc(actorx, game);
}
#include "../src/ac_ev_broker_move.c_inc"
+303
View File
@@ -0,0 +1,303 @@
static void aEBRK_set_request_act(EV_BROKER_ACTOR* broker) {
broker->npc_class.request.act_priority = 4;
broker->npc_class.request.act_idx = aNPC_ACT_SPECIAL;
broker->npc_class.request.act_type = aNPC_ACT_TYPE_SEARCH;
}
static void aEBRK_set_pl_talk_lock(EV_BROKER_ACTOR* broker, u8 flag) {
if (broker->pl_talk_lock != flag) {
if (flag == TRUE) {
mPlib_Set_able_force_speak_label(&broker->npc_class.actor_class);
} else {
mPlib_Reset_able_force_speak_label();
}
broker->pl_talk_lock = flag;
}
}
static int aEBRK_check_start_around_sub(ACTOR* check_actor, ACTOR* actorx, f32 pos_x, f32 pos_z) {
int res = TRUE;
while (check_actor != NULL) {
if (check_actor != actorx) {
f32 dist_x = check_actor->world.position.x - pos_x;
f32 dist_z = check_actor->world.position.z - pos_z;
if (SQ(dist_x) + SQ(dist_z) < SQ(mFI_UNIT_BASE_SIZE_F)) {
res = FALSE;
break;
}
}
check_actor = check_actor->next_actor;
}
return res;
}
static int aEBRK_check_start_around(ACTOR* actorx, GAME* game) {
static int part[] = { ACTOR_PART_NPC, ACTOR_PART_BG };
f32 pos_x = actorx->world.position.x;
f32 pos_z = actorx->world.position.z;
int i;
int res = TRUE;
for (i = 0; i < ARRAY_COUNT(part); i++) {
if (!aEBRK_check_start_around_sub(((GAME_PLAY*)game)->actor_info.list[part[i]].actor, actorx, pos_x, pos_z)) {
res = FALSE;
break;
}
}
return res;
}
static void aEBRK_check_tent(ACTOR* actorx, GAME* game) {
EV_BROKER_ACTOR* broker = (EV_BROKER_ACTOR*)actorx;
ACTOR* tent_actor = broker->tent_actor;
if (broker->tent_actor == NULL) {
broker->tent_actor =
Actor_info_name_search(&((GAME_PLAY*)game)->actor_info, mAc_PROFILE_BRSHOP, ACTOR_PART_ITEM);
} else if (tent_actor->id != mAc_PROFILE_BRSHOP || (tent_actor->mv_proc == NULL && tent_actor->dw_proc == NULL)) {
Actor_delete(actorx);
}
}
static int aEBRK_get_sell_item_sum(void) {
mActor_name_t* sell_item_p = Save_Get(event_save_data).special.event.broker.items;
int sum = 0;
int i;
for (i = 0; i < ARRAY_COUNT(Save_Get(event_save_data).special.event.broker.items); i++) {
if (*sell_item_p != EMPTY_NO) {
sum++;
}
sell_item_p++;
}
return sum;
}
static int aEBRK_check_pl_list(PersonalID_c* pid, int n) {
int res = -1;
int i;
for (i = 0; i < n; i++) {
if (mPr_CheckCmpPersonalID(pid, &Now_Private->player_ID) == TRUE) {
res = i;
}
pid++;
}
return res;
}
static void aEBRK_talk_wait(EV_BROKER_ACTOR* broker) {
int animeSeqNo = aNPC_ANIM_WAIT1;
if (chase_angle(&broker->npc_class.actor_class.shape_info.rotation.y, DEG2SHORT_ANGLE2(0.0f),
DEG2SHORT_ANGLE2(5.625f)) == FALSE) {
animeSeqNo = aNPC_ANIM_WALK1;
}
broker->npc_class.actor_class.world.angle.y = broker->npc_class.actor_class.shape_info.rotation.y;
if (broker->npc_class.draw.animation_id != animeSeqNo) {
Common_Get(clip).npc_clip->animation_init_proc(&broker->npc_class.actor_class, animeSeqNo, FALSE);
}
}
static void aEBRK_turn(EV_BROKER_ACTOR* broker) {
if (broker->npc_class.actor_class.shape_info.rotation.y == broker->npc_class.movement.mv_angl) {
broker->action_step = aNPC_ACTION_END_STEP;
}
}
static void aEBRK_enter(EV_BROKER_ACTOR* broker) {
ACTOR* actorx = &broker->npc_class.actor_class;
f32 walk_dist = actorx->home.position.z - actorx->world.position.z;
if (walk_dist > 60.0f) {
broker->action_step = aNPC_ACTION_END_STEP;
}
}
static void aEBRK_set_spd_info(EV_BROKER_ACTOR* broker, int action) {
if (action == aEBRK_ACTION_ENTER) {
broker->npc_class.movement.max_speed = 1.0f;
broker->npc_class.movement.acceleration = 0.1f;
broker->npc_class.movement.deceleration = 0.1f;
} else {
broker->npc_class.actor_class.speed = 0.0f;
broker->npc_class.movement.max_speed = 0.0f;
broker->npc_class.movement.acceleration = 0.0f;
broker->npc_class.movement.deceleration = 0.0f;
}
}
static void aEBRK_setupAction(EV_BROKER_ACTOR* broker, int action) {
static aEBRK_ACT_PROC process[] = {
&aEBRK_talk_wait,
&aEBRK_turn,
&aEBRK_enter,
(aEBRK_ACT_PROC)&none_proc1,
};
broker->action_step = 0;
broker->action = action;
broker->action_proc = process[action];
aEBRK_set_animation(broker, action);
aEBRK_set_spd_info(broker, action);
}
static void aEBRK_act_chg_data_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
nactorx->action.act_obj = aNPC_ACT_OBJ_PLAYER;
}
static void aEBRK_act_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
EV_BROKER_ACTOR* broker = (EV_BROKER_ACTOR*)nactorx;
nactorx->action.step = 0;
aEBRK_setupAction(broker, broker->next_action);
}
static void aEBRK_act_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
EV_BROKER_ACTOR* broker = (EV_BROKER_ACTOR*)nactorx;
(*broker->action_proc)(broker);
}
static void aEBRK_act_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc) {
static aNPC_SUB_PROC act_proc[] = {
&aEBRK_act_init_proc,
&aEBRK_act_chg_data_proc,
&aEBRK_act_main_proc,
};
(*act_proc[proc])(nactorx, play);
}
static void aEBRK_think_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
EV_BROKER_ACTOR* broker = (EV_BROKER_ACTOR*)nactorx;
if (nactorx->action.step == aNPC_ACTION_END_STEP) {
aEBRK_set_request_act(broker);
if (nactorx->action.idx == aNPC_ACT_TALK) {
nactorx->movement.mv_angl = DEG2SHORT_ANGLE2(180.0f);
nactorx->movement.mv_add_angl = DEG2SHORT_ANGLE2(11.25f);
broker->next_action = aEBRK_ACTION_TURN;
mPlib_request_main_demo_wait_type1(&play->game, 0, NULL);
}
} else if (broker->action_step == aNPC_ACTION_END_STEP) {
switch (broker->action) {
case aEBRK_ACTION_TURN:
nactorx->condition_info.demo_flg =
aNPC_COND_DEMO_SKIP_ENTRANCE_CHECK | aNPC_COND_DEMO_SKIP_HEAD_LOOKAT |
aNPC_COND_DEMO_SKIP_TALK_CHECK | aNPC_COND_DEMO_SKIP_ITEM | aNPC_COND_DEMO_SKIP_FORWARD_CHECK |
aNPC_COND_DEMO_SKIP_BGCHECK | aNPC_COND_DEMO_SKIP_OBJ_COL_CHECK | aNPC_COND_DEMO_SKIP_MOVE_Y |
aNPC_COND_DEMO_SKIP_MOVE_CIRCLE_REV | aNPC_COND_DEMO_SKIP_MOVE_RANGE_CHECK;
aEBRK_setupAction(broker, aEBRK_ACTION_ENTER);
break;
case aEBRK_ACTION_ENTER:
nactorx->condition_info.hide_request = TRUE;
mPlib_request_main_wait_type3(&play->game);
aEBRK_set_pl_talk_lock(broker, FALSE);
aEBRK_setupAction(broker, aEBRK_ACTION_HIDE);
break;
}
}
}
static void aEBRK_think_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
EV_BROKER_ACTOR* broker = (EV_BROKER_ACTOR*)nactorx;
nactorx->think.interrupt_flags = 0;
nactorx->action.act_proc = &aEBRK_act_proc;
aEBRK_set_request_act(broker);
}
static void aEBRK_think_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc) {
static aNPC_SUB_PROC think_proc[] = {
&aEBRK_think_init_proc,
&aEBRK_think_main_proc,
};
(*think_proc[proc])(nactorx, play);
}
static void aEBRK_schedule_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
nactorx->think.think_proc = &aEBRK_think_proc;
Common_Get(clip).npc_clip->think_proc(nactorx, play, aNPC_THINK_SPECIAL, 0);
}
static void aEBRK_schedule_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
if (!Common_Get(clip).npc_clip->think_proc(nactorx, play, -1, 1)) {
Common_Get(clip).npc_clip->think_proc(nactorx, play, -1, 2);
}
}
static void aEBRK_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc) {
static aNPC_SUB_PROC sche_proc[] = {
&aEBRK_schedule_init_proc,
&aEBRK_schedule_main_proc,
};
(*sche_proc[proc])(nactorx, play);
}
static void aEBRK_set_talk_info_talk_request(ACTOR* actorx) {
int msg_no;
u8 item_name[mIN_ITEM_NAME_LEN];
mActor_name_t item;
int idx;
idx = aEBRK_check_pl_list(Save_Get(event_save_data).special.event.broker.pid,
ARRAY_COUNT(Save_Get(event_save_data).special.event.broker.pid));
if (idx != -1) {
item = Save_Get(event_save_data).special.event.broker.sold_items[idx];
mIN_copy_name_str(item_name, item);
mMsg_SET_ITEM_STR_ART(mMsg_ITEM_STR2, item_name, mIN_ITEM_NAME_LEN, item);
msg_no = 0x078A;
} else {
idx = aEBRK_check_pl_list(&Common_Get(special_event_common).broker.entered_pid, 1);
if (idx != -1) {
msg_no = 0x0789;
} else {
msg_no = 0x788;
}
}
mDemo_Set_msg_num(msg_no);
aEBRK_set_pl_talk_lock((EV_BROKER_ACTOR*)actorx, TRUE);
}
static void aEBRK_talk_request(ACTOR* actorx, GAME* game) {
mDemo_Request(mDemo_TYPE_TALK, actorx, &aEBRK_set_talk_info_talk_request);
}
static int aEBRK_talk_init(ACTOR* actorx, GAME* game) {
EV_BROKER_ACTOR* broker = (EV_BROKER_ACTOR*)actorx;
broker->npc_class.talk_info.talk_request_proc = (aNPC_TALK_REQUEST_PROC)&none_proc1;
mDemo_Set_ListenAble();
return TRUE;
}
static int aEBRK_talk_end_chk(ACTOR* actorx, GAME* game) {
int res = FALSE;
if (mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE) {
res = TRUE;
}
return res;
}
static void aEBRK_actor_move(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->move_proc(actorx, game);
aEBRK_check_tent(actorx, game);
}