Implement & link ac_ev_pumpkin

This commit is contained in:
Cuyler36
2025-03-24 21:43:48 -04:00
parent 0d96b07102
commit 479ed07308
5 changed files with 483 additions and 3 deletions
+1 -1
View File
@@ -1174,7 +1174,7 @@ config.libs = [
Object(Matching, "actor/npc/event/ac_ev_kabuPeddler.c"),
Object(Matching, "actor/npc/event/ac_ev_majin.c"),
Object(Matching, "actor/npc/event/ac_ev_miko.c"),
Object(NonMatching, "actor/npc/event/ac_ev_pumpkin.c"),
Object(Matching, "actor/npc/event/ac_ev_pumpkin.c"),
Object(Matching, "actor/npc/event/ac_ev_santa.c"),
Object(Matching, "actor/npc/event/ac_ev_soncho.c"),
Object(Matching, "actor/npc/event/ac_ev_soncho2.c"),
+19 -1
View File
@@ -3,11 +3,30 @@
#include "types.h"
#include "m_actor.h"
#include "ac_npc.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ev_pumpkin_common_s {
s8 bx;
s8 bz;
} aEv_pumpkin_common_c;
typedef struct ev_pumpkin_actor_s EV_PUMPKIN_ACTOR;
typedef void (*aEPK_TALK_PROC)(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play);
struct ev_pumpkin_actor_s {
NPC_ACTOR npc_class;
int talk_action;
aEPK_TALK_PROC talk_proc;
aEv_pumpkin_common_c* common_p;
mActor_name_t present;
mActor_name_t item;
};
extern ACTOR_PROFILE Ev_Pumpkin_Profile;
#ifdef __cplusplus
@@ -15,4 +34,3 @@ extern ACTOR_PROFILE Ev_Pumpkin_Profile;
#endif
#endif
+5 -1
View File
@@ -34,6 +34,11 @@ enum {
aHOI_PRESENT_TYPE_NUM
};
// You must include m_common_data.h to use these macros
#define aHOI_CLIP CLIP(handOverItem_clip)
#define aHOI_TRANSFER_DONE() (aHOI_CLIP->master_actor == NULL)
#define aHOI_TRANSFER_IN_PROGRESS() (aHOI_CLIP->master_actor != NULL)
typedef struct hand_over_item_actor_s HANDOVERITEM_ACTOR;
typedef ACTOR* (*aHOI_BIRTH_PROC)(mActor_name_t, int, int, ACTOR*);
@@ -78,4 +83,3 @@ extern ACTOR_PROFILE HandOverItem_Profile;
#endif
#endif
+116
View File
@@ -0,0 +1,116 @@
#include "ac_ev_pumpkin.h"
#include "m_common_data.h"
#include "m_player_lib.h"
#include "m_msg.h"
#include "m_font.h"
#include "m_melody.h"
#include "m_bgm.h"
enum {
aEPK_FIRST_CALL_TALK_PROC,
aEPK_TRICK_OR_TREAT_TALK_PROC,
aEPK_MENU_OPEN_WAIT_TALK_PROC,
aEPK_MENU_CLOSE_WAIT_TALK_PROC,
aEPK_GET_OTHER_ITEM_WAIT_TALK_PROC,
aEPK_RECEIVE_TOOL_ITEM_START_WAIT_TALK_PROC,
aEPK_RECEIVE_TOOL_ITEM_END_WAIT_TALK_PROC,
aEPK_TRICK_TIMING_WAIT_TALK_PROC,
aEPK_TRICK_CHG_CLOTH_TALK_PROC,
aEPK_TRICK_CHG_CLOTH_END_WAIT_TALK_PROC,
aEPK_GET_AME_WAIT_TALK_PROC,
aEPK_GET_AME_TALK_PROC,
aEPK_GIVE_A_PRESENT_DEMO_START_WAIT_TALK_PROC,
aEPK_GIVE_A_PRESENT_DEMO_END_WAIT_TALK_PROC,
aEPK_PL_DEMO_CODE_END_WAIT_TALK_PROC,
aEPK_END_TALK,
aEPK_TALK_NUM
};
enum {
aEPK_TRICK_TYPE_CLOTH,
aEPK_TRICK_TYPE_ITEM,
aEPK_TRICK_TYPE_NUM
};
static void aEPK_actor_ct(ACTOR* actorx, GAME* game);
static void aEPK_actor_dt(ACTOR* actorx, GAME* game);
static void aEPK_actor_init(ACTOR* actorx, GAME* game);
static void aEPK_actor_move(ACTOR* actorx, GAME* game);
static void aEPK_actor_draw(ACTOR* actorx, GAME* game);
static void aEPK_actor_save(ACTOR* actorx, GAME* game);
// clang-format off
ACTOR_PROFILE Ev_Pumpkin_Profile = {
mAc_PROFILE_EV_PUMPKIN,
ACTOR_PART_NPC,
ACTOR_STATE_NONE,
EMPTY_NO,
ACTOR_OBJ_BANK_KEEP,
sizeof(EV_PUMPKIN_ACTOR),
&aEPK_actor_ct,
&aEPK_actor_dt,
&aEPK_actor_init,
mActor_NONE_PROC1,
&aEPK_actor_save,
};
// clang-format on
static void aEPK_talk_request(ACTOR* actorx, GAME* game);
static int aEPK_talk_init(ACTOR* actorx, GAME* game);
static int aEPK_talk_end_chk(ACTOR* actorx, GAME* game);
static void aEPK_change_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, int talk_action);
static void aEPK_actor_ct(ACTOR* actorx, GAME* game) {
static aNPC_ct_data_c ct_data = {
// clang-format off
&aEPK_actor_move,
&aEPK_actor_draw,
aNPC_CT_SCHED_TYPE_WANDER,
aEPK_talk_request,
aEPK_talk_init,
aEPK_talk_end_chk,
0,
// clang-format on
};
if (NPC_CLIP->birth_check_proc(actorx, game) == TRUE) {
EV_PUMPKIN_ACTOR* pumpkin = (EV_PUMPKIN_ACTOR*)actorx;
aEv_pumpkin_common_c* common_p;
NPC_CLIP->ct_proc(actorx, game, &ct_data);
pumpkin->npc_class.palActorIgnoreTimer = -1;
common_p = (aEv_pumpkin_common_c*)mEv_get_common_area(mEv_EVENT_HALLOWEEN, 0);
if (common_p == NULL) {
common_p = (aEv_pumpkin_common_c*)mEv_reserve_common_area(mEv_EVENT_HALLOWEEN, 0);
}
pumpkin->common_p = common_p;
}
}
static void aEPK_actor_save(ACTOR* actorx, GAME* game) {
NPC_CLIP->save_proc(actorx, game);
}
static void aEPK_actor_dt(ACTOR* actorx, GAME* game) {
NPC_CLIP->dt_proc(actorx, game);
mEv_actor_dying_message(mEv_EVENT_HALLOWEEN, actorx);
}
static void aEPK_actor_init(ACTOR* actorx, GAME* game) {
NPC_CLIP->init_proc(actorx, game);
}
static void aEPK_actor_move(ACTOR* actorx, GAME* game) {
NPC_CLIP->move_proc(actorx, game);
}
static void aEPK_actor_draw(ACTOR* actorx, GAME* game) {
NPC_CLIP->draw_proc(actorx, game);
}
#include "../src/actor/npc/event/ac_ev_pumpkin_talk.c_inc"
@@ -0,0 +1,342 @@
static int aEPK_get_trick_type(void) {
int count = 0;
int idx[mPr_POCKETS_SLOT_COUNT];
mActor_name_t* pocket_p = Now_Private->inventory.pockets;
int i;
int ret = aEPK_TRICK_TYPE_CLOTH;
for (i = 0; i < mPr_POCKETS_SLOT_COUNT; i++) {
switch (ITEM_NAME_GET_TYPE(*pocket_p)) {
case NAME_TYPE_FTR0:
case NAME_TYPE_FTR1:
if ((NowPrivate_GetItemCond(i) & mPr_ITEM_COND_QUEST) == 0) {
int ftr_idx = mRmTp_FtrItemNo2FtrIdx(*pocket_p);
// skip jack-o'-lantern and jack-in-the-box
if (ftr_idx != 0x127 && ftr_idx != 0x131) {
idx[count] = i;
count++;
}
}
break;
case NAME_TYPE_ITEM1:
if (ITEM_NAME_GET_CAT(*pocket_p) != ITEM1_CAT_TOOL && (NowPrivate_GetItemCond(i) & mPr_ITEM_COND_QUEST) == 0) {
idx[count] = i;
count++;
}
break;
}
pocket_p++;
}
if (count > 0 && RANDOM_F(1.0f) < 0.5f) {
mActor_name_t new_item;
mSP_SelectRandomItem_New(NULL, &new_item, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_HALLOWEEN2, FALSE);
mPr_SetPossessionItem(Now_Private, idx[RANDOM(count)], new_item, mPr_ITEM_COND_NORMAL);
mDemo_Set_OrderValue(mDemo_ORDER_PLAYER, 0, 0xFD);
ret = aEPK_TRICK_TYPE_ITEM;
}
return ret;
}
static void aEPK_restart_msg_win(int msg_no) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
mMsg_request_main_appear_wait_type1(msg_p);
mMsg_ChangeMsgData(msg_p, msg_no);
mMsg_Set_ForceNext(msg_p);
mMsg_Unset_LockContinue(msg_p);
}
static void aEPK_decide_present(EV_PUMPKIN_ACTOR* pumpkin) {
mActor_name_t present;
switch (RANDOM(12)) {
case 0:
present = ITM_CARPET17;
break;
case 1:
present = ITM_WALL17;
break;
default:
mSP_SelectRandomItem_New(NULL, &present, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_HALLOWEEN, FALSE);
break;
}
pumpkin->present = present;
}
static void aEPK_first_call_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
mMsg_SET_CONTINUE_MSG_NUM(0x09B5);
aEPK_change_talk_proc(pumpkin, aEPK_TRICK_OR_TREAT_TALK_PROC);
}
static void aEPK_trick_or_treat_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
if (order != 0 && mMsg_Check_MainNormalContinue(msg_p) == TRUE) {
int talk_act;
if (mChoice_GET_CHOSENUM() == mChoice_CHOICE0) {
mMsg_request_main_disappear_wait_type1(msg_p);
talk_act = aEPK_MENU_OPEN_WAIT_TALK_PROC;
} else {
talk_act = aEPK_TRICK_TIMING_WAIT_TALK_PROC;
}
aEPK_change_talk_proc(pumpkin, talk_act);
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
}
static void aEPK_menu_open_wait_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
if (mMsg_Check_main_wait(msg_p) == TRUE) {
Submenu* submenu = &play->submenu;
mSM_open_submenu(submenu, mSM_OVL_INVENTORY, mSM_IV_OPEN_GIVE, 0);
mMsg_Set_LockContinue(msg_p);
aEPK_change_talk_proc(pumpkin, aEPK_MENU_CLOSE_WAIT_TALK_PROC);
}
}
static void aEPK_menu_close_wait_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
Submenu* submenu = &play->submenu;
if (submenu->open_flag == FALSE) {
Submenu_Item_c* item_p = submenu->item_p;
mActor_name_t item = item_p->item;
int talk_act;
int remove_item = TRUE;
pumpkin->item = item;
if (item == EMPTY_NO) {
talk_act = aEPK_TRICK_TIMING_WAIT_TALK_PROC;
aEPK_restart_msg_win(0x09B6);
remove_item = FALSE;
} else if (item != ITM_FOOD_CANDY) {
// @BUG - damaged axe variants are not considered here
if ((item >= ITM_NET && item <= ITM_ROD) || (item >= ITM_GOLDEN_NET && item <= ITM_GOLDEN_ROD)) {
remove_item = FALSE;
}
talk_act = aEPK_GET_OTHER_ITEM_WAIT_TALK_PROC;
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 1, 3);
} else {
aEPK_decide_present(pumpkin);
talk_act = aEPK_GET_AME_WAIT_TALK_PROC;
aEPK_restart_msg_win(0x09B9);
}
if (remove_item == TRUE) {
mPr_SetPossessionItem(Now_Private, item_p->slot_no, EMPTY_NO, mPr_ITEM_COND_NORMAL);
}
aEPK_change_talk_proc(pumpkin, talk_act);
}
}
static void aEPK_get_other_item_wait_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
if (aHOI_TRANSFER_DONE()) {
int talk_act = aEPK_TRICK_TIMING_WAIT_TALK_PROC;
mActor_name_t item = pumpkin->item;
int msg_no = 0x09B8;
// @BUG - damaged axe variants are not considered here
if ((item >= ITM_NET && item <= ITM_ROD) || (item >= ITM_GOLDEN_NET && item <= ITM_GOLDEN_ROD)) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 1, 0);
msg_no = 0x09BB;
talk_act = aEPK_RECEIVE_TOOL_ITEM_START_WAIT_TALK_PROC;
}
aEPK_restart_msg_win(msg_no);
aEPK_change_talk_proc(pumpkin, talk_act);
}
}
static void aEPK_receive_tool_item_start_wait_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 1);
if (order == 2) {
aNPC_DEMO_GIVE_ITEM(pumpkin->item, aHOI_REQUEST_PUTAWAY, TRUE);
mMsg_SET_LOCKCONTINUE();
aEPK_change_talk_proc(pumpkin, aEPK_RECEIVE_TOOL_ITEM_END_WAIT_TALK_PROC);
}
}
static void aEPK_receive_tool_item_end_wait_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
if (mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 1) == 0 && aHOI_TRANSFER_DONE()) {
mMsg_UNSET_LOCKCONTINUE();
aEPK_change_talk_proc(pumpkin, aEPK_TRICK_TIMING_WAIT_TALK_PROC);
}
}
static void aEPK_trick_timing_wait_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
if (order != 0) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
int talk_action;
if (aEPK_get_trick_type() == aEPK_TRICK_TYPE_CLOTH) {
talk_action = aEPK_TRICK_CHG_CLOTH_TALK_PROC;
} else {
talk_action = aEPK_PL_DEMO_CODE_END_WAIT_TALK_PROC;
}
mMsg_Set_LockContinue(msg_p);
aEPK_change_talk_proc(pumpkin, talk_action);
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
}
static void aEPK_trick_chg_cloth_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
if (mPlib_get_player_actor_main_index((GAME*)play) == mPlayer_INDEX_CHANGE_CLOTH) {
aEPK_change_talk_proc(pumpkin, aEPK_TRICK_CHG_CLOTH_END_WAIT_TALK_PROC);
} else {
mPlib_request_main_change_cloth_forNPC_type1((GAME*)play, ITM_CLOTH017, 17, FALSE);
}
}
static void aEPK_trick_chg_cloth_end_wait_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
if (mPlib_get_player_actor_main_index((GAME*)play) != mPlayer_INDEX_CHANGE_CLOTH) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
mMsg_Unset_LockContinue(msg_p);
mMsg_Set_ForceNext(msg_p);
mMsg_ChangeMsgData(msg_p, 0x09B7);
aEPK_change_talk_proc(pumpkin, aEPK_END_TALK);
}
}
static void aEPK_get_ame_wait_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 1);
if (order == 3 && aHOI_TRANSFER_IN_PROGRESS()) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
mMsg_Set_LockContinue(msg_p);
aEPK_change_talk_proc(pumpkin, aEPK_GET_AME_TALK_PROC);
}
}
static void aEPK_get_ame_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
if (aHOI_TRANSFER_DONE()) {
mMsg_UNSET_LOCKCONTINUE();
aEPK_change_talk_proc(pumpkin, aEPK_GIVE_A_PRESENT_DEMO_START_WAIT_TALK_PROC);
}
}
static void aEPK_give_a_present_demo_start_wait_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
if (mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 1) == 2) {
aNPC_DEMO_GIVE_ITEM(ITM_PRESENT, aHOI_REQUEST_PUTAWAY, TRUE);
mMsg_SET_LOCKCONTINUE();
mPr_SetFreePossessionItem(Now_Private, pumpkin->present, mPr_ITEM_COND_PRESENT);
}
if (aHOI_TRANSFER_IN_PROGRESS()) {
aEPK_change_talk_proc(pumpkin, aEPK_GIVE_A_PRESENT_DEMO_END_WAIT_TALK_PROC);
}
}
static void aEPK_give_a_present_demo_end_wait_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
if (aHOI_TRANSFER_DONE()) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
mMsg_Unset_LockContinue(msg_p);
mMsg_Set_continue_msg_num(msg_p, 0x09BA);
aEPK_change_talk_proc(pumpkin, aEPK_END_TALK);
}
}
static void aEPK_pl_demo_code_end_wait_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, GAME_PLAY* play) {
if (mDemo_Get_OrderValue(mDemo_ORDER_PLAYER, 0) == 0) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
mMsg_Unset_LockContinue(msg_p);
mMsg_Set_ForceNext(msg_p);
mMsg_ChangeMsgData(msg_p, 0x09B7);
aEPK_change_talk_proc(pumpkin, aEPK_END_TALK);
}
}
static void aEPK_change_talk_proc(EV_PUMPKIN_ACTOR* pumpkin, int talk_act) {
static aEPK_TALK_PROC talk_proc[] = {
// clang-format off
aEPK_first_call_talk_proc,
aEPK_trick_or_treat_talk_proc,
aEPK_menu_open_wait_talk_proc,
aEPK_menu_close_wait_talk_proc,
aEPK_get_other_item_wait_talk_proc,
aEPK_receive_tool_item_start_wait_talk_proc,
aEPK_receive_tool_item_end_wait_talk_proc,
aEPK_trick_timing_wait_talk_proc,
aEPK_trick_chg_cloth_talk_proc,
aEPK_trick_chg_cloth_end_wait_talk_proc,
aEPK_get_ame_wait_talk_proc,
aEPK_get_ame_talk_proc,
aEPK_give_a_present_demo_start_wait_talk_proc,
aEPK_give_a_present_demo_end_wait_talk_proc,
aEPK_pl_demo_code_end_wait_talk_proc,
(aEPK_TALK_PROC)none_proc1,
// clang-format on
};
pumpkin->talk_proc = talk_proc[talk_act];
}
static void aEPK_set_talk_info(ACTOR* actorx) {
EV_PUMPKIN_ACTOR* pumpkin;
int msg_no;
int talk_act;
aEv_pumpkin_common_c* common_p;
GAME_PLAY* play;
play = (GAME_PLAY*)gamePT;
pumpkin = (EV_PUMPKIN_ACTOR*)actorx;
common_p = pumpkin->common_p;
mEv_set_status(mEv_EVENT_HALLOWEEN, mEv_STATUS_TALK);
if (play->block_table.block_x == common_p->bx && play->block_table.block_z == common_p->bz) {
int rnd = RANDOM(6);
msg_no = 0x09BC + rnd;
talk_act = aEPK_END_TALK;
} else {
msg_no = 0x098A;
talk_act = aEPK_FIRST_CALL_TALK_PROC;
}
mDemo_Set_msg_num(msg_no);
aEPK_change_talk_proc(pumpkin, talk_act);
common_p->bx = play->block_table.block_x;
common_p->bz = play->block_table.block_z;
}
static void aEPK_talk_request(ACTOR* actorx, GAME* game) {
mDemo_Request(mDemo_TYPE_TALK, actorx, aEPK_set_talk_info);
}
static int aEPK_talk_init(ACTOR* actorx, GAME* game) {
mDemo_Set_ListenAble();
return TRUE;
}
static int aEPK_talk_end_chk(ACTOR* actorx, GAME* game) {
EV_PUMPKIN_ACTOR* pumpkin = (EV_PUMPKIN_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
int ret = FALSE;
(*pumpkin->talk_proc)(pumpkin, play);
if (mDemo_CAN_ACTOR_TALK(actorx)) {
NPC_CLIP->chg_schedule_proc((NPC_ACTOR*)actorx, play, aNPC_SCHEDULE_TYPE_WANDER);
ret = TRUE;
}
return ret;
}