Implement & link ac_ev_gypsy

This commit is contained in:
Cuyler36
2023-12-19 07:58:39 -05:00
parent b39ffc4de8
commit 5a73b944d1
4 changed files with 311 additions and 0 deletions
+4
View File
@@ -547,6 +547,10 @@ ac_groundhog_control.c:
ac_ev_dokutu.c:
.text: [0x8051DFF4, 0x8051E228]
.data: [0x806A05C8, 0x806A0608]
ac_ev_gypsy.c:
.text: [0x80520D78, 0x80521414]
.rodata: [0x80649228, 0x80649238]
.data: [0x806A0938, 0x806A09F8]
ac_ev_soncho.c:
.text: [0x8052400C, 0x8052475C]
.rodata: [0x80649270, 0x80649278]
+17
View File
@@ -3,11 +3,28 @@
#include "types.h"
#include "m_actor.h"
#include "ac_npc.h"
#ifdef __cplusplus
extern "C" {
#endif
#define aEGPS_FORTUNE_PRICE 50
typedef struct ev_gypsy_actor_s EV_GYPSY_ACTOR;
typedef void (*aEGPS_TALK_INIT_PROC)(EV_GYPSY_ACTOR*, GAME_PLAY*);
typedef void (*aEGPS_TALK_PROC)(EV_GYPSY_ACTOR*, GAME_PLAY*);
typedef void (*aEGPS_TALK_SETUP_PROC)(EV_GYPSY_ACTOR*, GAME_PLAY*, int);
struct ev_gypsy_actor_s {
NPC_ACTOR npc_class;
int talk_action;
aEGPS_TALK_PROC talk_proc;
aEGPS_TALK_SETUP_PROC setup_talk_proc;
int fortune_given;
};
extern ACTOR_PROFILE Ev_Gypsy_Profile;
#ifdef __cplusplus
+93
View File
@@ -0,0 +1,93 @@
#include "ac_ev_gypsy.h"
#include "m_choice.h"
#include "m_common_data.h"
#include "m_item_name.h"
#include "m_msg.h"
#include "m_play.h"
#include "m_string.h"
enum {
aEGPS_ACTION_TALK_END_WAIT,
aEGPS_ACTION_CALL_IN,
aEGPS_ACTION_DECIDE_RESULT,
aEGPS_ACTION_DECIDE_RESULT2,
aEGPS_ACTION_NUM
};
enum {
aEGPS_STR_TYPE_ADJECTIVE,
aEGPS_STR_TYPE_NOUN,
aEGPS_STR_TYPE_VERB,
aEGPS_STR_TYPE_PLACE,
aEGPS_STR_TYPE_NUM
};
static void aEGPS_actor_ct(ACTOR*, GAME*);
static void aEGPS_actor_dt(ACTOR*, GAME*);
static void aEGPS_actor_move(ACTOR*, GAME*);
static void aEGPS_actor_draw(ACTOR*, GAME*);
static void aEGPS_actor_save(ACTOR*, GAME*);
static void aEGPS_actor_init(ACTOR*, GAME*);
ACTOR_PROFILE Ev_Gypsy_Profile = {
mAc_PROFILE_EV_GYPSY,
ACTOR_PART_NPC,
ACTOR_STATE_NONE,
SP_NPC_GYPSY,
ACTOR_OBJ_BANK_KEEP,
sizeof(EV_GYPSY_ACTOR),
&aEGPS_actor_ct,
&aEGPS_actor_dt,
&aEGPS_actor_init,
mActor_NONE_PROC1,
&aEGPS_actor_save
};
static void aEGPS_talk_request(ACTOR* actorx, GAME* game);
static int aEGPS_talk_init(ACTOR* actorx, GAME* game);
static int aEGPS_talk_end_chk(ACTOR* actorx, GAME* game);
static void aEGPS_setupAction(EV_GYPSY_ACTOR* gypsy, GAME_PLAY* play, int action);
static void aEGPS_actor_ct(ACTOR* actorx, GAME* game) {
static aNPC_ct_data_c ct_data = {
&aEGPS_actor_move,
&aEGPS_actor_draw,
2,
&aEGPS_talk_request,
&aEGPS_talk_init,
&aEGPS_talk_end_chk,
0
};
EV_GYPSY_ACTOR* gypsy = (EV_GYPSY_ACTOR*)actorx;
if ((*Common_Get(clip).npc_clip->birth_check_proc)(actorx, game) == TRUE) {
(*Common_Get(clip).npc_clip->ct_proc)(actorx, game, &ct_data);
actorx->talk_distance = 80.0f;
actorx->status_data.weight = 255;
actorx->world.position.x += 20.0f;
gypsy->setup_talk_proc = &aEGPS_setupAction;
}
}
static void aEGPS_actor_save(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->save_proc)(actorx, game);
}
static void aEGPS_actor_dt(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->dt_proc)(actorx, game);
mEv_actor_dying_message(mEv_EVENT_GYPSY, actorx);
}
static void aEGPS_actor_init(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->init_proc)(actorx, game);
}
static void aEGPS_actor_draw(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->draw_proc)(actorx, game);
}
#include "../src/ac_ev_gypsy_move.c_inc"
+197
View File
@@ -0,0 +1,197 @@
static void aEGPS_set_string(int type) {
static int string_num[aEGPS_STR_TYPE_NUM] = { 0x1A4, 0x1C4, 0x184, 0x164 };
u8 str[mIN_ITEM_NAME_LEN];
int str_no = RANDOM(32) + string_num[type];
mString_Load_StringFromRom(str, sizeof(str), str_no);
mMsg_Set_item_str(mMsg_Get_base_window_p(), type, str, sizeof(str));
}
static void aEGPS_call_in(EV_GYPSY_ACTOR* gypsy, GAME_PLAY* play) {
static int msg_no[] = {
0x971, /* 'No' choice */
0x973, /* 'Yes' choice */
0x972 /* 'Yes' choice, but not enough Bells */
};
static int next_act_idx[] = {
aEGPS_ACTION_TALK_END_WAIT,
aEGPS_ACTION_DECIDE_RESULT,
aEGPS_ACTION_TALK_END_WAIT
};
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
if (mMsg_Check_MainNormalContinue(msg_p) == TRUE) {
int type = -1;
switch (mChoice_Get_ChoseNum(mChoice_Get_base_window_p())) {
case mChoice_CHOICE0: /* Yes */
if (Common_Get(now_private)->inventory.wallet >= aEGPS_FORTUNE_PRICE) {
type = 1; // yes
}
else {
type = 2; // not enough bells
}
break;
case mChoice_CHOICE1: /* No */
type = 0; // no
break;
}
if (type != -1) {
mMsg_Set_continue_msg_num(msg_p, msg_no[type]);
(*gypsy->setup_talk_proc)(gypsy, play, next_act_idx[type]);
}
}
}
static void aEGPS_decide_result(EV_GYPSY_ACTOR* gypsy, GAME_PLAY* play) {
static int msg_no[] = {
0x974,
0x975,
0x976,
0x977,
0x978,
0x979
};
static int msg_no2[] = {
0x97C,
0x97D,
0x97E,
0x97F,
0x980
};
static u8 destiny[] = {
mPr_DESTINY_NORMAL,
mPr_DESTINY_POPULAR,
mPr_DESTINY_UNPOPULAR,
mPr_DESTINY_BAD_LUCK,
mPr_DESTINY_MONEY_LUCK,
mPr_DESTINY_GOODS_LUCK
};
int demo_order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
int selected;
if (demo_order != 0) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
if (gypsy->talk_action == aEGPS_ACTION_DECIDE_RESULT) {
selected = RANDOM(10);
if (selected < 4) {
selected = 4; /* 50% chance of 'normal' luck, 10% chance for other types */
}
selected -= 4;
Common_Get(now_private)->destiny.type = destiny[selected];
mMsg_Set_continue_msg_num(msg_p, msg_no[selected]);
}
else {
/* aEGPS_ACTION_DECIDE_RESULT2 */
selected = Common_Get(now_private)->destiny.type - 1;
mMsg_Set_continue_msg_num(msg_p, msg_no2[selected]);
}
(*gypsy->setup_talk_proc)(gypsy, play, aEGPS_ACTION_TALK_END_WAIT);
}
}
static void aEGPS_decide_result_init(EV_GYPSY_ACTOR* gypsy, GAME_PLAY* play) {
u32 wallet = Common_Get(now_private)->inventory.wallet;
wallet -= aEGPS_FORTUNE_PRICE;
Common_Get(now_private)->inventory.wallet = wallet;
aEGPS_set_string(aEGPS_STR_TYPE_ADJECTIVE);
aEGPS_set_string(aEGPS_STR_TYPE_NOUN);
aEGPS_set_string(aEGPS_STR_TYPE_VERB);
aEGPS_set_string(aEGPS_STR_TYPE_PLACE);
gypsy->fortune_given = TRUE;
}
static void aEGPS_init_proc(EV_GYPSY_ACTOR* gypsy, GAME_PLAY* play, int action) {
static aEGPS_TALK_INIT_PROC init_proc[aEGPS_ACTION_NUM] = {
(aEGPS_TALK_INIT_PROC)&none_proc1,
(aEGPS_TALK_INIT_PROC)&none_proc1,
&aEGPS_decide_result_init,
(aEGPS_TALK_INIT_PROC)&none_proc1
};
(*init_proc[action])(gypsy, play);
}
static void aEGPS_setupAction(EV_GYPSY_ACTOR* gypsy, GAME_PLAY* play, int action) {
static aEGPS_TALK_PROC process[aEGPS_ACTION_NUM] = {
(aEGPS_TALK_PROC)&none_proc1,
&aEGPS_call_in,
&aEGPS_decide_result,
&aEGPS_decide_result
};
gypsy->talk_action = action;
gypsy->talk_proc = process[action];
aEGPS_init_proc(gypsy, play, action);
}
static void aEGPS_set_talk_info(ACTOR* actorx) {
EV_GYPSY_ACTOR* gypsy = (EV_GYPSY_ACTOR*)actorx;
int msg_num;
if (gypsy->fortune_given == TRUE) {
msg_num = 0x982; // Fortune given msg but scene not reloaded?
}
else if (Common_Get(now_private)->destiny.type == mPr_DESTINY_NORMAL) {
msg_num = 0x970; // Should fortune be given?
}
else {
msg_num = 0x97B; // Fortune given msg after scene was reloaded?
}
mDemo_Set_msg_num(msg_num);
}
static void aEGPS_talk_request(ACTOR* actorx, GAME* game) {
mDemo_Request(mDemo_TYPE_TALK, actorx, &aEGPS_set_talk_info);
}
static int aEGPS_talk_init(ACTOR* actorx, GAME* game) {
EV_GYPSY_ACTOR* gypsy = (EV_GYPSY_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
int next_act_idx;
if (Common_Get(now_private)->destiny.type == mPr_DESTINY_NORMAL) {
next_act_idx = aEGPS_ACTION_CALL_IN;
}
else {
next_act_idx = aEGPS_ACTION_DECIDE_RESULT2;
}
(*gypsy->setup_talk_proc)(gypsy, play, next_act_idx);
mDemo_Set_ListenAble();
return TRUE;
}
static int aEGPS_talk_end_chk(ACTOR* actorx, GAME* game) {
EV_GYPSY_ACTOR* gypsy = (EV_GYPSY_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
int res = FALSE;
(*gypsy->talk_proc)(gypsy, play);
if (mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE) {
res = TRUE;
}
return res;
}
static void aEGPS_actor_move(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->move_proc)(actorx, game);
if (mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE) {
chase_angle(&actorx->shape_info.rotation.y, 0, DEG2SHORT_ANGLE(5.625f));
actorx->world.angle.y = actorx->shape_info.rotation.y;
}
}