Add a few more rel groups

This commit is contained in:
Cuyler36
2024-10-29 05:54:49 -04:00
parent 941f2d1e03
commit 192a8a6ca3
68 changed files with 80 additions and 65 deletions
View File
+126
View File
@@ -0,0 +1,126 @@
#include "ac_npc_curator.h"
#include "m_common_data.h"
#include "m_item_name.h"
#include "m_msg.h"
enum {
aCR_ACTION_WAIT,
aCR_ACTION_SLEEP_WAIT,
aCR_ACTION_SLEEP,
aCR_ACTION_NUM
};
enum {
aCR_TALK_END_WAIT,
aCR_TALK_AFTER_TALK_START_WAIT,
aCR_TALK_CHK_REQUEST,
aCR_TALK_CHK_DECIDE_TO_DONATE,
aCR_TALK_CHK_DECIDE_TO_DONATE2,
aCR_TALK_MENU_OPEN_WAIT,
aCR_TALK_MSG_WIN_CLOSE_WAIT,
aCR_TALK_MENU_CLOSE_WAIT,
aCR_TALK_GET_DEMO_START_WAIT,
aCR_TALK_GET_DEMO_END_WAIT,
aCR_TALK_MSG_WIN_OPEN_WAIT,
aCR_TALK_RETURN_DEMO_START_WAIT,
aCR_TALK_RETURN_DEMO_START_WAIT2,
aCR_TALK_RETURN_DEMO_END_WAIT,
aCR_TALK_RETURN_DEMO_END_WAIT2,
aCR_TALK_CHK_CONTINUE_TO_DONATE,
aCR_TALK_CHK_CONTINUE_TO_DONATE2,
aCR_TALK_CHK_CONTINUE_TO_DONATE3,
aCR_TALK_PUTAWAY_DEMO_START_WAIT,
aCR_TALK_PUTAWAY_DEMO_START_WAIT2,
aCR_TALK_PUTAWAY_DEMO_START_WAIT3,
aCR_TALK_PUTAWAY_DEMO_START_WAIT4,
aCR_TALK_PUTAWAY_DEMO_START_WAIT5,
aCR_TALK_PUTAWAY_DEMO_START_WAIT6,
aCR_TALK_PUTAWAY_DEMO_START_WAIT5_2,
aCR_TALK_PUTAWAY_DEMO_END_WAIT,
aCR_TALK_PUTAWAY_DEMO_END_WAIT2,
aCR_TALK_PUTAWAY_DEMO_END_WAIT3,
aCR_TALK_PUTAWAY_DEMO_END_WAIT4,
aCR_TALK_PUTAWAY_DEMO_END_WAIT5,
aCR_TALK_PUTAWAY_DEMO_END_WAIT6,
aCR_TALK_AFTER_EXPLAIN_INSECT,
aCR_TALK_THANKS_FOSSIL_MSG_END_WAIT,
aCR_TALK_CHK_ALL_COMPLETE,
aCR_TALK_NUM
};
static void aCR_actor_ct(ACTOR* actorx, GAME* game);
static void aCR_actor_dt(ACTOR* actorx, GAME* game);
static void aCR_actor_move(ACTOR* actorx, GAME* game);
static void aCR_actor_draw(ACTOR* actorx, GAME* game);
static void aCR_actor_init(ACTOR* actorx, GAME* game);
static void aCR_actor_save(ACTOR* actorx, GAME* game);
ACTOR_PROFILE Npc_Curator_Profile = {
mAc_PROFILE_NPC_CURATOR,
ACTOR_PART_NPC,
ACTOR_STATE_NONE,
SP_NPC_CURATOR,
ACTOR_OBJ_BANK_KEEP,
sizeof(NPC_CURATOR_ACTOR),
&aCR_actor_ct,
&aCR_actor_dt,
&aCR_actor_init,
mActor_NONE_PROC1,
&aCR_actor_save
};
static void aCR_talk_request(ACTOR* actorx, GAME* game);
static int aCR_talk_init(ACTOR* actorx, GAME* game);
static int aCR_talk_end_chk(ACTOR* actorx, GAME* game);
static void aCR_schedule_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int sched_idx);
static void aCR_setupTalkAction(NPC_CURATOR_ACTOR* curator, GAME_PLAY* play, int talk_act_idx);
static void aCR_setupAction(NPC_CURATOR_ACTOR* curator, GAME_PLAY* play, int action);
static void aCR_actor_ct(ACTOR* actorx, GAME* game) {
static aNPC_ct_data_c ct_data = {
&aCR_actor_move,
&aCR_actor_draw,
5,
&aCR_talk_request,
&aCR_talk_init,
&aCR_talk_end_chk,
0
};
NPC_CURATOR_ACTOR* curator = (NPC_CURATOR_ACTOR*)actorx;
if ((*Common_Get(clip).npc_clip->birth_check_proc)(actorx, game) == TRUE) {
curator->npc_class.schedule.schedule_proc = &aCR_schedule_proc;
(*Common_Get(clip).npc_clip->ct_proc)(actorx, game, &ct_data);
actorx->status_data.weight = 255;
actorx->world.position.x += 20.0f;
curator->setupTalkAction_proc = &aCR_setupTalkAction;
/* Clear 'first talk' flag if entering from a scene outside the museum */
if (Common_Get(last_scene_no) >= SCENE_MY_ROOM_LL1 || Common_Get(last_scene_no) < SCENE_MUSEUM_ROOM_PAINTING) {
aNPC_SPNPC_BIT_CLR(Common_Get(spnpc_first_talk_flags), aNPC_SPNPC_BIT_CURATOR);
}
}
}
static void aCR_actor_save(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->save_proc)(actorx, game);
}
static void aCR_actor_dt(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->dt_proc)(actorx, game);
}
static void aCR_actor_init(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->init_proc)(actorx, game);
}
static void aCR_actor_draw(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->draw_proc)(actorx, game);
}
#include "../src/actor/ac_npc_curator_move.c_inc"
File diff suppressed because it is too large Load Diff
+72
View File
@@ -0,0 +1,72 @@
#include "ac_npc_engineer.h"
#include "m_name_table.h"
#include "m_common_data.h"
extern void aNEG_actor_ct(ACTOR* actor, GAME* game);
extern void aNEG_actor_dt(ACTOR* actor, GAME* game);
extern void aNEG_actor_init(ACTOR* actor, GAME* game);
extern void aNEG_actor_save(ACTOR* actor, GAME* game);
ACTOR_PROFILE Npc_Engineer_Profile = {
mAc_PROFILE_NPC_ENGINEER,
ACTOR_PART_NPC,
ACTOR_STATE_CAN_MOVE_IN_DEMO_SCENES | ACTOR_STATE_NO_MOVE_WHILE_CULLED,
EMPTY_NO,
ACTOR_OBJ_BANK_KEEP,
sizeof(NPCENGINEER_ACTOR),
aNEG_actor_ct,
aNEG_actor_dt,
aNEG_actor_init,
mActor_NONE_PROC1,
aNEG_actor_save,
};
void aNEG_actor_move(ACTOR*, GAME*);
void aNEG_actor_draw(ACTOR*, GAME*);
void aNEG_actor_ct(ACTOR* actor, GAME* game){
static aNPC_ct_data_c ct_data = {
&aNEG_actor_move,
&aNEG_actor_draw,
5,
NULL,
NULL,
NULL,
0,
};
NPCENGINEER_ACTOR* engineer = (NPCENGINEER_ACTOR*)actor;
if(Common_Get(clip.npc_clip)->birth_check_proc(actor,game) == TRUE){
engineer->npc_class.schedule.schedule_proc = (aNPC_SCHEDULE_PROC)mActor_NONE_PROC1;
Common_Get(clip.npc_clip)->ct_proc(actor,game,&ct_data);
engineer->npc_class.condition_info.demo_flg = -1;
engineer->npc_class.condition_info.hide_request = 0;
engineer->npc_class.palActorIgnoreTimer = -1;
engineer->npc_class.actor_class.status_data.weight = MASSTYPE_HEAVY;
engineer->npc_class.actor_class.shape_info.rotation.y = 0x4000;
engineer->npc_class.actor_class.world.angle.y = 0x4000;
engineer->npc_class.movement.mv_angl = 0x4000;
engineer->npc_class.request.act_priority = 4;
engineer->npc_class.request.act_idx = 0;
engineer->npc_class.request.act_type = 0;
}
}
void aNEG_actor_save(ACTOR* actor, GAME* game) {
Common_Get(clip.npc_clip)->save_proc(actor,game);
}
void aNEG_actor_dt(ACTOR* actor, GAME* game) {
Common_Get(clip.npc_clip)->dt_proc(actor,game);
}
void aNEG_actor_init(ACTOR* actor, GAME* game) {
Common_Get(clip.npc_clip)->init_proc(actor,game);
}
void aNEG_actor_move(ACTOR* actor, GAME* game){
Common_Get(clip.npc_clip)->move_proc(actor,game);
}
void aNEG_actor_draw(ACTOR* actor, GAME* game) {
Common_Get(clip.npc_clip)->draw_proc(actor,game);
}
+152
View File
@@ -0,0 +1,152 @@
#include "ac_npc_guide.h"
#include "m_play.h"
#include "m_common_data.h"
#include "ac_train_door.h"
#include "m_player_lib.h"
#include "m_font.h"
#include "m_msg.h"
#include "m_timeIn_ovl.h"
#include "m_ledit_ovl.h"
#include "libultra/libultra.h"
#include "m_bgm.h"
#include "m_soncho.h"
enum {
aNGD_ACTION_ENTER,
aNGD_ACTION_APPROACH,
aNGD_ACTION_TALK_START_WAIT,
aNGD_ACTION_TIME_CHECK,
aNGD_ACTION_SDON_AND_PB_WAIT,
aNGD_ACTION_TIME_MENU_OPEN_WAIT,
aNGD_ACTION_TIME_MENU_CLOSE_WAIT,
aNGD_ACTION_MSG_WIN_OPEN_WAIT,
aNGD_ACTION_CONFIRM_INPUT_DATA,
aNGD_ACTION_WAIT_PERMISSION,
aNGD_ACTION_SITDOWN,
aNGD_ACTION_PNAME_MENU_OPEN_WAIT,
aNGD_ACTION_PNAME_MENU_CLOSE_WAIT,
aNGD_ACTION_SEX_SELECT_WAIT,
aNGD_ACTION_SEX_SELECT_WAIT2,
aNGD_ACTION_SEX_SELECT_AFTER,
aNGD_ACTION_CNAME_MENU_OPEN_WAIT,
aNGD_ACTION_CNAME_MENU_CLOSE_WAIT,
aNGD_ACTION_STANDUP_START_WAIT,
aNGD_ACTION_STANDUP,
aNGD_ACTION_MOVE_READY,
aNGD_ACTION_MOVE_TO_AISLE,
aNGD_ACTION_MOVE_TO_DOOR,
aNGD_ACTION_MOVE_TO_DECK,
aNGD_ACTION_KEITAI_ON,
aNGD_ACTION_KEITAI_TALK,
aNGD_ACTION_KEITAI_OFF,
aNGD_ACTION_OPEN_DOOR,
aNGD_ACTION_RETURN_APPROACH,
aNGD_ACTION_LAST_TALK_START_WAIT,
aNGD_ACTION_SITDOWN2_START_WAIT,
aNGD_ACTION_SITDOWN2,
aNGD_ACTION_LAST_TALK_END_WAIT,
aNGD_ACTION_SCENE_CHANGE_WAIT,
aNGD_ACTION_NUM
};
enum {
aNGD_OBJ_LOOK_TYPE_NORMAL,
aNGD_OBJ_LOOK_TYPE_TALK,
aNGD_OBJ_LOOK_TYPE_NUM
};
static void aNGD_actor_ct(ACTOR* actorx, GAME* game);
static void aNGD_actor_dt(ACTOR* actorx, GAME* game);
static void aNGD_actor_init(ACTOR* actorx, GAME* game);
static void aNGD_actor_save(ACTOR* actorx, GAME* game);
// clang-format off
ACTOR_PROFILE Npc_Guide_Profile = {
mAc_PROFILE_NPC_GUIDE,
ACTOR_PART_NPC,
ACTOR_STATE_NO_DRAW_WHILE_CULLED | ACTOR_STATE_NO_MOVE_WHILE_CULLED,
SP_NPC_GUIDE,
ACTOR_OBJ_BANK_KEEP,
sizeof(NPC_GUIDE_ACTOR),
&aNGD_actor_ct,
&aNGD_actor_dt,
&aNGD_actor_init,
mActor_NONE_PROC1,
&aNGD_actor_save,
};
// clang-format on
static void aNGD_actor_move(ACTOR* actorx, GAME* game);
static void aNGD_actor_draw(ACTOR* actorx, GAME* game);
static void aNGD_setupAction(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play, int action);
static void aNGD_actor_ct(ACTOR* actorx, GAME* game) {
static aNPC_ct_data_c ct_data = { &aNGD_actor_move, &aNGD_actor_draw, 0, NULL, NULL, NULL, 0 };
NPC_GUIDE_ACTOR* guide = (NPC_GUIDE_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
PLAYER_ACTOR* player;
Common_Get(clip).npc_clip->ct_proc(actorx, game, &ct_data);
guide->npc_class.condition_info.hide_flg = FALSE; // show guide actor
guide->npc_class.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;
guide->camera_morph_counter = 40;
guide->obj_look_type = aNGD_OBJ_LOOK_TYPE_NORMAL;
guide->npc_class.eye_y = 30.0f;
guide->camera_move_set_counter = 1;
guide->npc_class.palActorIgnoreTimer = -1;
guide->train_door_actor = Actor_info_fgName_search(&play->actor_info, TRAIN_DOOR, ACTOR_PART_BG);
guide->npc_class.actor_class.shape_info.draw_shadow = TRUE;
guide->npc_class.actor_class.world.position.z = 130.0f;
/* Put the player into demo wait state */
mPlib_request_main_demo_wait_type1(game, 0, NULL);
player = GET_PLAYER_ACTOR(play);
if (player != NULL) {
/* Make the player invisible during the intro train ride */
player->actor_class.state_bitfield |= ACTOR_STATE_INVISIBLE;
}
aNGD_setupAction(guide, play, aNGD_ACTION_ENTER);
/* Play train noises sfx repeatedly */
sAdo_SysLevStart(NA_SE_TRAIN_RIDE);
/* Disable sunlight */
Common_Set(sunlight_flag, FALSE);
/* Turn on echo for sound effects */
sAdo_TrgSeEcho(TRUE);
sAdo_LevSeEcho(TRUE);
}
static void aNGD_actor_save(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->save_proc(actorx, game);
}
static void aNGD_actor_dt(ACTOR* actorx, GAME* game) {
/* Update all animals in town to have this town's info */
mNpc_SetAnimalThisLand(Save_Get(animals), ANIMAL_NUM_MAX);
Common_Get(clip).npc_clip->dt_proc(actorx, game);
/* Stop train noise sfx */
sAdo_SysLevStop(NA_SE_TRAIN_RIDE);
}
static void aNGD_actor_init(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->init_proc(actorx, game);
}
static void aNGD_actor_draw(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->draw_proc(actorx, game);
}
#include "../src/actor/ac_npc_guide_animation.c_inc"
#include "../src/actor/ac_npc_guide_move.c_inc"
+138
View File
@@ -0,0 +1,138 @@
#include "ac_npc_guide2.h"
#include "m_play.h"
#include "m_common_data.h"
#include "ac_train_door.h"
#include "m_player_lib.h"
#include "m_font.h"
#include "m_msg.h"
#include "m_timeIn_ovl.h"
#include "m_ledit_ovl.h"
#include "libultra/libultra.h"
#include "m_bgm.h"
#include "m_soncho.h"
enum {
aNG2_ACTION_ENTER,
aNG2_ACTION_APPROACH,
aNG2_ACTION_TALK_START_WAIT,
aNG2_ACTION_WAIT_PERMISSION,
aNG2_ACTION_SITDOWN,
aNG2_ACTION_SDON_AND_PB_WAIT,
aNG2_ACTION_PNAME_MENU_OPEN_WAIT,
aNG2_ACTION_PNAME_MENU_CLOSE_WAIT,
aNG2_ACTION_MSG_WIN_OPEN_WAIT,
aNG2_ACTION_PNAME_NG,
aNG2_ACTION_SEX_SELECT_WAIT,
aNG2_ACTION_SEX_SELECT_WAIT2,
aNG2_ACTION_SEX_SELECT_AFTER,
aNG2_ACTION_STANDUP_START_WAIT,
aNG2_ACTION_STANDUP,
aNG2_ACTION_MOVE_READY,
aNG2_ACTION_MOVE_TO_AISLE,
aNG2_ACTION_MOVE_TO_DOOR,
aNG2_ACTION_MOVE_TO_DECK,
aNG2_ACTION_KEITAI_ON,
aNG2_ACTION_KEITAI_TALK,
aNG2_ACTION_KEITAI_OFF,
aNG2_ACTION_OPEN_DOOR,
aNG2_ACTION_RETURN_APPROACH,
aNG2_ACTION_LAST_TALK_START_WAIT,
aNG2_ACTION_SITDOWN2_START_WAIT,
aNG2_ACTION_SITDOWN2,
aNG2_ACTION_LAST_TALK_END_WAIT,
aNG2_ACTION_SCENE_CHANGE_WAIT,
aNG2_ACTION_NUM
};
enum {
aNG2_OBJ_LOOK_TYPE_NORMAL,
aNG2_OBJ_LOOK_TYPE_TALK,
aNG2_OBJ_LOOK_TYPE_NUM
};
static void aNG2_actor_ct(ACTOR* actorx, GAME* game);
static void aNG2_actor_dt(ACTOR* actorx, GAME* game);
static void aNG2_actor_init(ACTOR* actorx, GAME* game);
static void aNG2_actor_save(ACTOR* actorx, GAME* game);
// clang-format off
ACTOR_PROFILE Npc_Guide2_Profile = {
mAc_PROFILE_NPC_GUIDE2,
ACTOR_PART_NPC,
ACTOR_STATE_NO_DRAW_WHILE_CULLED | ACTOR_STATE_NO_MOVE_WHILE_CULLED,
SP_NPC_GUIDE2,
ACTOR_OBJ_BANK_KEEP,
sizeof(NPC_GUIDE2_ACTOR),
&aNG2_actor_ct,
&aNG2_actor_dt,
&aNG2_actor_init,
mActor_NONE_PROC1,
&aNG2_actor_save,
};
// clang-format on
static void aNG2_actor_move(ACTOR* actorx, GAME* game);
static void aNG2_actor_draw(ACTOR* actorx, GAME* game);
static void aNG2_setupAction(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play, int action);
static void aNG2_actor_ct(ACTOR* actorx, GAME* game) {
static aNPC_ct_data_c ct_data = { &aNG2_actor_move, &aNG2_actor_draw, 0, NULL, NULL, NULL, 0 };
NPC_GUIDE2_ACTOR* guide2 = (NPC_GUIDE2_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
PLAYER_ACTOR* player;
Common_Get(clip).npc_clip->ct_proc(actorx, game, &ct_data);
guide2->npc_class.condition_info.hide_flg = FALSE; // show guide2 actor
guide2->npc_class.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;
guide2->camera_morph_counter = 40;
guide2->obj_look_type = aNG2_OBJ_LOOK_TYPE_NORMAL;
guide2->npc_class.eye_y = 30.0f;
guide2->camera_move_set_counter = 1;
guide2->npc_class.palActorIgnoreTimer = -1;
guide2->train_door_actor = Actor_info_fgName_search(&play->actor_info, TRAIN_DOOR, ACTOR_PART_BG);
guide2->npc_class.actor_class.shape_info.draw_shadow = TRUE;
guide2->npc_class.actor_class.world.position.z = 130.0f;
/* Put the player into demo wait state */
mPlib_request_main_demo_wait_type1(game, 0, NULL);
player = GET_PLAYER_ACTOR(play);
if (player != NULL) {
/* Make the player invisible during the intro train ride */
player->actor_class.state_bitfield |= ACTOR_STATE_INVISIBLE;
}
aNG2_setupAction(guide2, play, aNG2_ACTION_ENTER);
/* Play train noises sfx repeatedly */
sAdo_SysLevStart(NA_SE_TRAIN_RIDE);
}
static void aNG2_actor_save(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->save_proc(actorx, game);
}
static void aNG2_actor_dt(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->dt_proc(actorx, game);
/* Stop train noise sfx */
sAdo_SysLevStop(NA_SE_TRAIN_RIDE);
}
static void aNG2_actor_init(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->init_proc(actorx, game);
}
static void aNG2_actor_draw(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->draw_proc(actorx, game);
}
#include "../src/actor/ac_npc_guide2_animation.c_inc"
#include "../src/actor/ac_npc_guide2_move.c_inc"
@@ -0,0 +1,45 @@
typedef struct npc_guide_animation_s {
int anim_id;
int talk_flag;
} aNG2_anime_c;
static void aNG2_set_animation(NPC_GUIDE2_ACTOR* guide2, int action) {
// clang-format off
static aNG2_anime_c anime[] = {
{ aNPC_ANIM_OPEN_D1, FALSE },
{ aNPC_ANIM_WALK1, FALSE },
{ aNPC_ANIM_WAIT1, TRUE },
{ aNPC_ANIM_WAIT1, TRUE },
{ aNPC_ANIM_SITDOWN_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_STANDUP_D1, FALSE },
{ aNPC_ANIM_WAIT1, FALSE },
{ aNPC_ANIM_WALK1, FALSE },
{ aNPC_ANIM_WALK1, FALSE },
{ aNPC_ANIM_TO_DECK_D1, FALSE },
{ aNPC_ANIM_KEITAI_ON1, FALSE },
{ aNPC_ANIM_KEITAI_TALK1, TRUE },
{ aNPC_ANIM_KEITAI_OFF1, FALSE },
{ aNPC_ANIM_OPEN_D2, FALSE },
{ aNPC_ANIM_WALK1, FALSE },
{ aNPC_ANIM_WAIT1, FALSE },
{ aNPC_ANIM_WAIT1, TRUE },
{ aNPC_ANIM_SITDOWN_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, FALSE },
};
// clang-format on
aNG2_anime_c* anime_info = &anime[action];
Common_Get(clip).npc_clip->animation_init_proc(&guide2->npc_class.actor_class, anime_info->anim_id,
anime_info->talk_flag);
}
+823
View File
@@ -0,0 +1,823 @@
static void aNG2_set_camera(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
static s8 mov_def_cnt[] = { 3, 0 };
static f32 obj_look_y_max[] = { 30.0f, 20.0f };
static f32 obj_look_y_spd[] = { 0.5f, 2.5f };
xyz_t eye;
xyz_t pos;
xyz_t ground;
s16 move;
f32 moveX;
f32 moveY;
int obj_look_type = guide2->obj_look_type;
s16 cur_angle;
f32 inter;
f32 sin;
f32 ground_y;
s16 angle;
move = guide2->camera_move;
guide2->camera_move += 0xE20;
angle = move;
angle += 0xE20;
moveX = cos_s(angle) * 0.1f;
angle = move;
angle += 0xE20;
moveY = sin_s(angle) * guide2->camera_move_range;
if (guide2->camera_move_y <= 0.0f && moveY >= 0.0f) {
s8 cnt = guide2->camera_move_cnt;
cnt--;
if (cnt < 0) {
s8 set_cnt = guide2->camera_move_set_counter;
set_cnt--;
if (set_cnt < 0) {
set_cnt = ARRAY_COUNT(mov_def_cnt) - 1;
}
guide2->camera_move_set_counter = set_cnt;
cnt = mov_def_cnt[set_cnt];
guide2->camera_move_range = 0.3f;
} else {
guide2->camera_move_range *= 0.35f;
}
guide2->camera_move_cnt = cnt;
}
guide2->camera_move_y = moveY;
cur_angle = guide2->camera_tilt_cur_angle;
chase_angle(&cur_angle, guide2->camera_tilt_goal_angle, guide2->camera_tilt_add);
guide2->camera_tilt_cur_angle = cur_angle;
sin = sin_s(cur_angle);
/* Set camera eye pos */
eye.x = moveX + sin * 20.0f + 100.0f;
eye.y = moveY + sin * -5.0f + 80.0f;
eye.z = 400.0f;
/* Move NPC head to current target */
chase_f(&guide2->npc_class.eye_y, obj_look_y_max[obj_look_type], obj_look_y_spd[obj_look_type] * 0.5f);
/* Set ground pos */
ground.x = guide2->npc_class.draw.shadow_pos.x;
ground.z = guide2->npc_class.draw.shadow_pos.z;
if (obj_look_type == aNG2_OBJ_LOOK_TYPE_TALK) {
/* Use the guide2's NPC shadow position for Y */
ground_y = guide2->npc_class.draw.shadow_pos.y;
} else {
/* Get the ground position for Y */
ground_y = mCoBG_GetBgY_OnlyCenter_FromWpos2(ground, 0.0f);
}
chase_f(&guide2->obj_dist_ground, ground_y, 0.5f);
ground.y = guide2->obj_dist_ground;
/* Set camera center pos */
if (guide2->lock_camera_flag == TRUE) {
pos.x = ground.x;
pos.y = ground.y + guide2->npc_class.eye_y;
pos.z = ground.z;
} else if (mDemo_Check(mDemo_TYPE_SPEAK, &guide2->npc_class.actor_class) == TRUE) {
int morph_counter = guide2->camera_morph_counter;
f32 r;
guide2->camera_morph_counter = morph_counter - 1;
if ((morph_counter - 1) == 0) {
guide2->lock_camera_flag = TRUE;
}
r = (40.0f - (f32)(morph_counter - 1)) / 40.0f;
inter = cKF_HermitCalc(r, 1.0f, 0.0f, 1.0f, 3.2f, 0.0f);
pos.x = (ground.x - 90.0f) * inter + 90.0f;
pos.y = ((ground.y + guide2->npc_class.eye_y) - 80.0f) * inter + 80.0f;
pos.z = (ground.z - 280.0f) * inter + 280.0f;
} else {
/* Default position */
pos.x = 90.0f;
pos.y = 80.0f;
pos.z = 280.0f;
}
pos.x += moveX;
pos.y += moveY;
Camera2_change_priority(play, 0);
Camera2_request_main_lock(play, &pos, &eye, 40.0f, 0, 60.0f, 800.0f, 5);
}
static void aNG2_set_camera_eyes(NPC_GUIDE2_ACTOR* guide2) {
if (guide2->camera_eyes_flag == TRUE) {
guide2->npc_class.request.head_pos.x = 100.0f;
guide2->npc_class.request.head_pos.y = guide2->npc_class.actor_class.eye.position.y;
guide2->npc_class.request.head_pos.z = 400.0f;
guide2->npc_class.request.head_priority = 3;
guide2->npc_class.request.head_type = 2;
}
}
static void aNG2_set_walk_spd(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
guide2->npc_class.movement.max_speed = 1.0f;
guide2->npc_class.movement.acceleration = 0.1f;
guide2->npc_class.movement.deceleration = 0.2f;
}
static void aNG2_set_walk_spd2(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
guide2->npc_class.movement.max_speed = 1.5f;
guide2->npc_class.movement.acceleration = 0.15f;
guide2->npc_class.movement.deceleration = 0.3f;
}
static void aNG2_set_stop_spd(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
guide2->npc_class.actor_class.speed = 0.0f;
guide2->npc_class.movement.max_speed = 0.0f;
guide2->npc_class.movement.acceleration = 0.0f;
guide2->npc_class.movement.deceleration = 0.0f;
}
static int aNG2_make_keitai(NPC_GUIDE2_ACTOR* guide2, GAME* game) {
int res = FALSE;
if (guide2->npc_class.right_hand.item_actor_p == NULL) {
if (Common_Get(clip).tools_clip != NULL) {
ACTOR* keitai = Common_Get(clip).tools_clip->aTOL_birth_proc(
TOOL_KEITAI, aTOL_ACTION_TAKEOUT, &guide2->npc_class.actor_class, game, -1, NULL);
if (keitai != NULL) {
guide2->npc_class.right_hand.item_actor_p = keitai;
res = TRUE;
}
}
} else {
res = TRUE;
}
return res;
}
static int aNG2_chg_cond_keitai(NPC_GUIDE2_ACTOR* guide2, int cond) {
int res = FALSE;
if (Common_Get(clip).tools_clip != NULL) {
if (Common_Get(clip).tools_clip->aTOL_chg_request_mode_proc(
&guide2->npc_class.actor_class, guide2->npc_class.right_hand.item_actor_p, cond) == TRUE) {
res = TRUE;
}
}
return res;
}
static void aNG2_talk_demo_proc(ACTOR* actorx) {
if (mDemo_Check(mDemo_TYPE_SPEAK, actorx) == TRUE) {
Common_Get(clip).npc_clip->talk_demo_proc(actorx);
}
}
static u8* aNG2_getP_other_pl_name(void) {
Private_c* priv;
u32 player_no;
int i;
player_no = Common_Get(player_no);
priv = Save_Get(private_data) + player_no;
/* Search for players before this one's player no */
for (i = player_no; i != 0; i--) {
priv--;
if (mPr_NullCheckPersonalID(&priv->player_ID) != TRUE) {
return priv->player_ID.player_name;
}
}
priv = Save_Get(private_data) + player_no;
/* Search for players after this one's player no */
for (i = (PLAYER_NUM - 1) - player_no; i != 0; i--) {
priv++;
if (mPr_NullCheckPersonalID(&priv->player_ID) != TRUE) {
return priv->player_ID.player_name;
}
}
/* No other players to reference */
return NULL;
}
static int aNG2_check_pname(void) {
int ok = TRUE;
int i;
for (i = 0; i < PLAYER_NUM; i++) {
Private_c* priv = Save_GetPointer(private_data[i]);
if (i != Common_Get(player_no)) {
if (mem_cmp(Now_Private->player_ID.player_name, priv->player_ID.player_name, PLAYER_NAME_LEN) == TRUE) {
/* Another player has the same name in this town */
ok = FALSE;
break;
}
}
}
return ok;
}
static void aNG2_check_talk_msg_no(NPC_GUIDE2_ACTOR* guide2) {
if (mDemo_Check(mDemo_TYPE_SPEAK, &guide2->npc_class.actor_class) == TRUE) {
int msg_no = mMsg_GET_MSG_NUM();
int flags;
switch (msg_no) {
case 0x2AC9:
flags = (1 << 3);
break;
case 0x2ADB:
flags = (1 << 2);
break;
case 0x2ADD:
flags = (1 << 1);
break;
case 0x2AD3:
flags = (1 << 0);
break;
default:
flags = 0;
break;
}
guide2->answer_flags |= flags;
}
}
static void aNG2_set_pl_face_type(NPC_GUIDE2_ACTOR* guide2) {
static int face_type_table[mPr_SEX_NUM][mPr_FACE_TYPE_NUM] = {
/* Male faces */
{
mPr_FACE_TYPE5,
mPr_FACE_TYPE6,
mPr_FACE_TYPE1,
mPr_FACE_TYPE4,
mPr_FACE_TYPE0,
mPr_FACE_TYPE2,
mPr_FACE_TYPE7,
mPr_FACE_TYPE3,
},
/* Female faces */
{
mPr_FACE_TYPE0,
mPr_FACE_TYPE5,
mPr_FACE_TYPE2,
mPr_FACE_TYPE6,
mPr_FACE_TYPE4,
mPr_FACE_TYPE7,
mPr_FACE_TYPE3,
mPr_FACE_TYPE1,
},
};
int answer_flags = guide2->answer_flags;
int face_type;
if ((answer_flags & 1) == 0) {
/* Select a random face for the player */
face_type = RANDOM(mPr_FACE_TYPE_NUM);
} else {
/* Select a face based on choices */
face_type = face_type_table[Now_Private->gender][answer_flags >> 1];
}
Now_Private->face = face_type;
}
static void aNG2_calc_body_angl(NPC_GUIDE2_ACTOR* guide2, f32 pos_x, f32 pos_z) {
f32 dX = pos_x - guide2->npc_class.actor_class.world.position.x;
f32 dZ = pos_z - guide2->npc_class.actor_class.world.position.z;
s16 angl = atans_table(dZ, dX);
chase_angle(&guide2->npc_class.actor_class.shape_info.rotation.y, angl, DEG2SHORT_ANGLE2(11.25f));
guide2->npc_class.actor_class.world.angle.y = guide2->npc_class.actor_class.shape_info.rotation.y;
}
static void aNG2_set_default_talk_info(void) {
mDemo_Set_camera(CAMERA2_PROCESS_NUM);
mDemo_Set_talk_change_player(FALSE);
mDemo_Set_use_zoom_sound(TRUE);
}
static void aNG2_enter(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
if (guide2->npc_class.draw.main_animation_state == cKF_STATE_STOPPED) {
guide2->camera_eyes_flag = TRUE;
aNG2_setupAction(guide2, play, aNG2_ACTION_APPROACH);
} else if (cKF_FrameControl_passCheck_now(&guide2->npc_class.draw.main_animation.keyframe.frame_control, 20.0f) ==
TRUE) {
TRAINDOOR_ACTOR* train_door = (TRAINDOOR_ACTOR*)guide2->train_door_actor;
train_door->open_flag = TRUE;
}
}
static void aNG2_approach(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
if (guide2->npc_class.actor_class.world.position.z >= 290.0f) {
guide2->npc_class.actor_class.world.position.z = 290.0f;
aNG2_setupAction(guide2, play, aNG2_ACTION_TALK_START_WAIT);
}
}
static void aNG2_set_talk_info_talk_start_wait(ACTOR* actorx) {
mMsg_SET_FREE_STR(mMsg_FREE_STR0, aNG2_getP_other_pl_name(), PLAYER_NAME_LEN);
mDemo_Set_msg_num(0x2AD5);
aNG2_set_default_talk_info();
((NPC_GUIDE2_ACTOR*)actorx)->obj_look_type = aNG2_OBJ_LOOK_TYPE_TALK;
}
static void aNG2_talk_start_wait(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
ACTOR* actorx = (ACTOR*)guide2;
if (mDemo_Check(mDemo_TYPE_SPEAK, actorx) == TRUE) {
if (mDemo_Check_ListenAble() == FALSE &&
chase_angle(&actorx->shape_info.rotation.y, actorx->player_angle_y, 0x400) == TRUE) {
guide2->camera_eyes_flag = FALSE;
aNG2_setupAction(guide2, play, aNG2_ACTION_WAIT_PERMISSION);
mDemo_Set_ListenAble();
}
} else {
mDemo_Request(mDemo_TYPE_SPEAK, actorx, &aNG2_set_talk_info_talk_start_wait);
}
}
static void aNG2_wait_permission(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
if (mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
aNG2_setupAction(guide2, play, aNG2_ACTION_SITDOWN);
}
}
static void aNG2_sitdown(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
guide2->npc_class.actor_class.world.position.x = 100.0f;
guide2->npc_class.actor_class.world.position.z = 280.0f;
guide2->npc_class.actor_class.shape_info.rotation.y = 0;
/* Wait for the sit animation to finish before continuing */
if (guide2->npc_class.draw.main_animation_state == cKF_STATE_STOPPED) {
mMsg_UNSET_LOCKCONTINUE();
guide2->next_action = aNG2_ACTION_PNAME_MENU_OPEN_WAIT;
aNG2_setupAction(guide2, play, aNG2_ACTION_SDON_AND_PB_WAIT);
}
}
static void aNG2_sdon_and_pb_wait(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
u16 order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
if (order != 0 && mMsg_CHECK_MAINNORMALCONTINUE()) {
aNG2_setupAction(guide2, play, guide2->next_action);
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
}
static void aNG2_pname_menu_open_wait(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
if (mMsg_CHECK_MAIN_WAIT() == TRUE) {
aNG2_setupAction(guide2, play, 7);
}
}
static void aNG2_pname_menu_close_wait(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
if (play->submenu.open_flag == FALSE) {
aNG2_setupAction(guide2, play, 8);
}
}
static void aNG2_msg_win_open_wait(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
static int msg_no[] = { 0x2ACA, 0x2AE2 };
static int next_act_idx[] = { 10, 9 };
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
if (mMsg_Check_not_series_main_wait(msg_p) == TRUE) {
int idx = 0;
mMsg_Unset_LockContinue(msg_p);
/* Check if the player's name already exists in town */
if (aNG2_check_pname() == FALSE) {
idx = 1;
}
mMsg_Set_continue_msg_num(msg_p, msg_no[idx]);
mMsg_Set_ForceNext(msg_p);
aNG2_setupAction(guide2, play, next_act_idx[idx]);
}
}
static void aNG2_sex_select_wait(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
if (mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0: // male
case mChoice_CHOICE1: // female
aNG2_setupAction(guide2, play, aNG2_ACTION_SEX_SELECT_WAIT2);
break;
case mChoice_CHOICE2: // 'That's not right'
guide2->next_action = aNG2_ACTION_PNAME_MENU_OPEN_WAIT;
aNG2_setupAction(guide2, play, aNG2_ACTION_SDON_AND_PB_WAIT);
break;
}
}
}
static void aNG2_sex_select_wait2(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
static int next_act_idx[] = { aNG2_ACTION_STANDUP_START_WAIT, aNG2_ACTION_SEX_SELECT_AFTER };
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
if (order != 0) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
if (mMsg_Check_MainNormalContinue(msg_p) == TRUE) {
int idx = -1;
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0: // male
switch (order) {
case 1: // That's right
Now_Private->gender = mPr_SEX_MALE;
break;
case 2: // I'm not a boy
Now_Private->gender = mPr_SEX_FEMALE;
break;
}
idx = 0;
mMsg_Set_continue_msg_num(msg_p, 0x2AD9);
mMsg_Set_ForceNext(msg_p);
break;
case mChoice_CHOICE1: // female
switch (order) {
case 1: // That's right
Now_Private->gender = mPr_SEX_FEMALE;
break;
case 2: // I'm not a girl
Now_Private->gender = mPr_SEX_MALE;
break;
}
idx = 1;
break;
}
if (idx != -1) {
aNG2_setupAction(guide2, play, next_act_idx[idx]);
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
}
}
}
static void aNG2_sex_select_after(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
u16 order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
if (order != 0 && mMsg_Check_MainNormalContinue(msg_p)) {
aNG2_setupAction(guide2, play, aNG2_ACTION_STANDUP_START_WAIT);
mMsg_Set_continue_msg_num(msg_p, 0x2AD9);
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
}
static void aNG2_standup_start_wait(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
/* Wait for guide2 to stop speaking to us */
if (mDemo_Check(mDemo_TYPE_SPEAK, &guide2->npc_class.actor_class) == FALSE) {
guide2->obj_look_type = aNG2_OBJ_LOOK_TYPE_NORMAL;
aNG2_setupAction(guide2, play, aNG2_ACTION_STANDUP);
}
}
static void aNG2_standup(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
/* Wait for animation to finish */
if (guide2->npc_class.draw.main_animation_state == cKF_STATE_STOPPED) {
aNG2_setupAction(guide2, play, guide2->next_action);
}
}
static void aNG2_move_ready(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
guide2->npc_class.actor_class.world.position.x = 100.0f;
guide2->npc_class.actor_class.world.position.z = 300.0f;
aNG2_setupAction(guide2, play, aNG2_ACTION_MOVE_TO_AISLE);
}
static void aNG2_move_to_aisle(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
aNG2_calc_body_angl(guide2, 140.0f, 290.0f);
if (guide2->npc_class.actor_class.world.position.x > 140.0f) {
aNG2_setupAction(guide2, play, aNG2_ACTION_MOVE_TO_DOOR);
}
}
static void aNG2_move_to_door(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
aNG2_calc_body_angl(guide2, 140.0f, 130.0f);
/* Check if we reached the door */
if (guide2->npc_class.actor_class.world.position.z < 130.0f) {
aNG2_setupAction(guide2, play, aNG2_ACTION_MOVE_TO_DECK);
}
/* Check if we should start rotating */
if (guide2->npc_class.draw.shadow_pos.z < 140.0f) {
guide2->camera_tilt_goal_angle = DEG2SHORT_ANGLE2(90.0f);
guide2->camera_tilt_add = DEG2SHORT_ANGLE2(2.8125f);
}
}
static void aNG2_move_to_deck(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
if (cKF_FrameControl_passCheck_now(&guide2->npc_class.draw.main_animation.keyframe.frame_control, 9.0f) == TRUE) {
TRAINDOOR_ACTOR* train_door = (TRAINDOOR_ACTOR*)guide2->train_door_actor;
train_door->open_flag = TRUE;
}
/* Reuse standup state to wait for animation to finish */
aNG2_standup(guide2, play);
}
static void aNG2_set_talk_info_keitai_on(ACTOR* actorx) {
mDemo_Set_msg_num(0x2ADE);
aNG2_set_default_talk_info();
}
static void aNG2_keitai_on(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
static f32 anmSpd[] = { 0.0f, 0.5f };
int idx = aNG2_make_keitai(guide2, &play->game);
guide2->npc_class.draw.main_animation.keyframe.frame_control.speed = anmSpd[idx];
if (idx != 0) {
if (mDemo_Check(mDemo_TYPE_SPEAK, (ACTOR*)guide2) == TRUE) {
if (mDemo_Check_ListenAble() == FALSE) {
mDemo_Set_ListenAble();
}
} else {
/* Request to start speaking */
mDemo_Request(mDemo_TYPE_SPEAK, (ACTOR*)guide2, &aNG2_set_talk_info_keitai_on);
}
}
/* Wait for animation to finish */
if (guide2->npc_class.draw.main_animation_state == cKF_STATE_STOPPED) {
aNG2_setupAction(guide2, play, aNG2_ACTION_KEITAI_TALK);
}
}
static void aNG2_keitai_talk(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
if (mDemo_Check(mDemo_TYPE_SPEAK, &guide2->npc_class.actor_class) == FALSE) {
aNG2_setupAction(guide2, play, aNG2_ACTION_KEITAI_OFF);
} else if (guide2->npc_class.draw.main_animation_state == cKF_STATE_STOPPED) {
Common_Get(clip).npc_clip->animation_init_proc(&guide2->npc_class.actor_class, aNPC_ANIM_KEITAI_TALK2, TRUE);
}
}
static void aNG2_open_door(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
chase_angle(&guide2->npc_class.actor_class.shape_info.rotation.y, DEG2SHORT_ANGLE2(-180.0f),
DEG2SHORT_ANGLE2(0.703125f));
if (cKF_FrameControl_passCheck_now(&guide2->npc_class.draw.main_animation.keyframe.frame_control, 22.0f) == TRUE) {
TRAINDOOR_ACTOR* train_door = (TRAINDOOR_ACTOR*)guide2->train_door_actor;
train_door->open_flag = TRUE;
if (guide2->npc_class.draw.shadow_pos.z < 140.0f) {
guide2->camera_tilt_goal_angle = 0;
guide2->camera_tilt_add = 0x600;
}
}
/* Reuse standup state to wait for animation to finish */
aNG2_standup(guide2, play);
}
static void aNG2_return_approach(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
guide2->npc_class.actor_class.world.position.x = 140.0f;
guide2->npc_class.actor_class.world.angle.y = 0;
guide2->npc_class.actor_class.shape_info.rotation.y = 0;
if (guide2->npc_class.actor_class.world.position.z > 290.0f) {
aNG2_setupAction(guide2, play, aNG2_ACTION_LAST_TALK_START_WAIT);
}
}
static void aNG2_set_talk_info_last_talk_start_wait(ACTOR* actorx) {
mDemo_Set_msg_num(0x2AD1);
aNG2_set_default_talk_info();
((NPC_GUIDE2_ACTOR*)actorx)->obj_look_type = aNG2_OBJ_LOOK_TYPE_TALK;
}
static void aNG2_last_talk_start_wait(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
ACTOR* actorx = (ACTOR*)guide2;
if (mDemo_Check(mDemo_TYPE_SPEAK, actorx) == TRUE) {
if (mDemo_Check_ListenAble() == FALSE &&
chase_angle(&actorx->shape_info.rotation.y, actorx->player_angle_y, 0x400) == TRUE) {
guide2->camera_eyes_flag = FALSE;
aNG2_setupAction(guide2, play, aNG2_ACTION_SITDOWN2_START_WAIT);
mDemo_Set_ListenAble();
}
} else {
mDemo_Request(mDemo_TYPE_SPEAK, actorx, &aNG2_set_talk_info_last_talk_start_wait);
}
}
static void aNG2_sitdown2_start_wait(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
u16 order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
if (order != 0) {
aNG2_setupAction(guide2, play, aNG2_ACTION_SITDOWN2);
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
}
static void aNG2_sitdown2(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
guide2->npc_class.actor_class.world.position.x = 100.0f;
guide2->npc_class.actor_class.world.position.z = 280.0f;
guide2->npc_class.actor_class.shape_info.rotation.y = 0;
/* Wait for animation to finish */
aNG2_standup(guide2, play);
}
static void aNG2_last_talk_end_wait(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
if (mDemo_Check(mDemo_TYPE_SPEAK, &guide2->npc_class.actor_class) == FALSE) {
aNG2_setupAction(guide2, play, aNG2_ACTION_SCENE_CHANGE_WAIT);
}
}
/* Init procs */
static void aNG2_sitdown_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
mMsg_SET_LOCKCONTINUE();
}
static void aNG2_pname_menu_open_wait_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
mMsg_Set_LockContinue(msg_p);
mMsg_request_main_disappear_wait_type1(msg_p);
}
static void aNG2_pname_menu_close_wait_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
Submenu* submenu = &play->submenu;
mSM_open_submenu(submenu, mSM_OVL_LEDIT, mLE_TYPE_PLAYER_NAME, 0);
}
static void aNG2_msg_win_open_wait_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
mMsg_REQUEST_MAIN_APPEAR_WAIT_TYPE1();
}
static void aNG2_pname_ng_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
guide2->next_action = 6;
}
static void aNG2_standup_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
guide2->next_action = aNG2_ACTION_MOVE_READY;
}
static void aNG2_move_ready_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
guide2->npc_class.draw.main_animation.keyframe.morph_counter = 0.0f;
}
static void aNG2_move_to_aisle_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
aNG2_set_walk_spd2(guide2, play);
}
static void aNG2_move_to_deck_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
aNG2_set_stop_spd(guide2, play);
guide2->npc_class.actor_class.world.position.x = 140.0f;
guide2->npc_class.actor_class.world.position.z = 130.0f;
guide2->next_action = aNG2_ACTION_KEITAI_ON;
}
static void aNG2_keitai_off_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
aNG2_chg_cond_keitai(guide2, aTOL_ACTION_PUTAWAY);
guide2->next_action = aNG2_ACTION_OPEN_DOOR;
}
static void aNG2_open_door_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
guide2->next_action = aNG2_ACTION_RETURN_APPROACH;
}
static void aNG2_return_approach_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
guide2->camera_eyes_flag = TRUE;
aNG2_set_walk_spd2(guide2, play);
guide2->npc_class.draw.main_animation.keyframe.morph_counter = 0.0f;
}
static void aNG2_sitdown2_start_wait_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
static void aNG2_sitdown2_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
guide2->npc_class.draw.main_animation.keyframe.morph_counter = 0.0f;
guide2->next_action = aNG2_ACTION_LAST_TALK_END_WAIT;
}
static void aNG2_last_talk_end_wait_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
aNG2_chg_cond_keitai(guide2, aTOL_ACTION_DESTRUCT);
guide2->npc_class.right_hand.item_actor_p = NULL;
}
static void aNG2_scene_change_wait_init(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play) {
/* Init next scene transition */
goto_next_scene(play, 0, 1);
play->fb_wipe_type = 3;
Common_Get(transition).wipe_type = 4;
mEv_SetFirstJob();
mEv_SetFirstIntro();
mEnv_DecideWeather_NormalGameStart();
aNG2_set_pl_face_type(guide2);
mPr_SetNowPrivateCloth();
Common_Set(submenu_disabled, TRUE);
mBGMPsComp_make_ps_wipe(0x41C2);
mBGMPsComp_scene_mode(18);
}
typedef void (*aNG2_INIT_PROC)(NPC_GUIDE2_ACTOR*, GAME_PLAY*);
static void aNG2_init_proc(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play, int action) {
static aNG2_INIT_PROC init_proc[] = {
(aNG2_INIT_PROC)&none_proc1,
&aNG2_set_walk_spd,
&aNG2_set_stop_spd,
(aNG2_INIT_PROC)&none_proc1,
&aNG2_sitdown_init,
(aNG2_INIT_PROC)&none_proc1,
&aNG2_pname_menu_open_wait_init,
&aNG2_pname_menu_close_wait_init,
&aNG2_msg_win_open_wait_init,
&aNG2_pname_ng_init,
(aNG2_INIT_PROC)&none_proc1,
(aNG2_INIT_PROC)&none_proc1,
(aNG2_INIT_PROC)&none_proc1,
(aNG2_INIT_PROC)&none_proc1,
&aNG2_standup_init,
&aNG2_move_ready_init,
&aNG2_move_to_aisle_init,
(aNG2_INIT_PROC)&none_proc1,
&aNG2_move_to_deck_init,
(aNG2_INIT_PROC)&none_proc1,
(aNG2_INIT_PROC)&none_proc1,
&aNG2_keitai_off_init,
&aNG2_open_door_init,
&aNG2_return_approach_init,
&aNG2_set_stop_spd,
&aNG2_sitdown2_start_wait_init,
&aNG2_sitdown2_init,
&aNG2_last_talk_end_wait_init,
&aNG2_scene_change_wait_init,
};
(*init_proc[action])(guide2, play);
}
static void aNG2_setupAction(NPC_GUIDE2_ACTOR* guide2, GAME_PLAY* play, int action) {
static aNG2_PROC process[] = {
&aNG2_enter,
&aNG2_approach,
&aNG2_talk_start_wait,
&aNG2_wait_permission,
&aNG2_sitdown,
&aNG2_sdon_and_pb_wait,
&aNG2_pname_menu_open_wait,
&aNG2_pname_menu_close_wait,
&aNG2_msg_win_open_wait,
&aNG2_sdon_and_pb_wait,
&aNG2_sex_select_wait,
&aNG2_sex_select_wait2,
&aNG2_sex_select_after,
&aNG2_standup_start_wait,
&aNG2_standup,
&aNG2_move_ready,
&aNG2_move_to_aisle,
&aNG2_move_to_door,
&aNG2_move_to_deck,
&aNG2_keitai_on,
&aNG2_keitai_talk,
&aNG2_standup,
&aNG2_open_door,
&aNG2_return_approach,
&aNG2_last_talk_start_wait,
&aNG2_sitdown2_start_wait,
&aNG2_sitdown2,
&aNG2_last_talk_end_wait,
(aNG2_PROC)&none_proc1,
};
guide2->action = action;
guide2->proc = process[action];
aNG2_set_animation(guide2, action);
aNG2_init_proc(guide2, play, action);
}
static void aNG2_actor_move(ACTOR* actorx, GAME* game) {
NPC_GUIDE2_ACTOR* guide2 = (NPC_GUIDE2_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
Common_Get(clip).npc_clip->move_before_proc(actorx, game);
aNG2_talk_demo_proc(actorx);
aNG2_check_talk_msg_no(guide2);
(*guide2->proc)(guide2, play);
Common_Get(clip).npc_clip->move_after_proc(actorx, game);
aNG2_set_camera(guide2, play);
aNG2_set_camera_eyes(guide2);
mSC_change_player_freeze(play);
}
@@ -0,0 +1,59 @@
typedef struct npc_guide_animation_s {
int anim_id;
int talk_flag;
} aNGD_anime_c;
static void aNGD_set_animation(NPC_GUIDE_ACTOR* guide, int action) {
// clang-format off
static aNGD_anime_c anime[] = {
{ aNPC_ANIM_OPEN_D1, FALSE },
{ aNPC_ANIM_WALK1, FALSE },
{ aNPC_ANIM_WAIT1, TRUE },
{ aNPC_ANIM_WAIT1, TRUE },
{ aNPC_ANIM_WAIT1, TRUE },
{ aNPC_ANIM_WAIT1, TRUE },
{ aNPC_ANIM_WAIT1, TRUE },
{ aNPC_ANIM_WAIT1, TRUE },
{ aNPC_ANIM_WAIT1, TRUE },
{ aNPC_ANIM_WAIT1, TRUE },
{ aNPC_ANIM_SITDOWN_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_STANDUP_D1, FALSE },
{ aNPC_ANIM_WAIT1, FALSE },
{ aNPC_ANIM_WALK1, FALSE },
{ aNPC_ANIM_WALK1, FALSE },
{ aNPC_ANIM_TO_DECK_D1, FALSE },
{ aNPC_ANIM_KEITAI_ON1, FALSE },
{ aNPC_ANIM_KEITAI_TALK1, TRUE },
{ aNPC_ANIM_KEITAI_OFF1, FALSE },
{ aNPC_ANIM_OPEN_D2, FALSE },
{ aNPC_ANIM_WALK1, FALSE },
{ aNPC_ANIM_WAIT1, FALSE },
{ aNPC_ANIM_WAIT1, TRUE },
{ aNPC_ANIM_SITDOWN_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, TRUE },
{ aNPC_ANIM_SITDOWN_WAIT_D1, FALSE },
};
// clang-format on
aNGD_anime_c* anime_info = &anime[action];
int anim_id = anime_info->anim_id;
int talk_flag = anime_info->talk_flag;
if ((action == aNGD_ACTION_SDON_AND_PB_WAIT || action == aNGD_ACTION_MSG_WIN_OPEN_WAIT ||
action == aNGD_ACTION_CONFIRM_INPUT_DATA) &&
guide->next_action != aNGD_ACTION_TIME_MENU_OPEN_WAIT &&
guide->next_action != aNGD_ACTION_TIME_MENU_CLOSE_WAIT) {
anim_id = aNPC_ANIM_SITDOWN_WAIT_D1;
talk_flag = TRUE;
}
Common_Get(clip).npc_clip->animation_init_proc(&guide->npc_class.actor_class, anim_id, talk_flag);
}
+908
View File
@@ -0,0 +1,908 @@
static void aNGD_set_camera(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
static s8 mov_def_cnt[] = { 3, 0 };
static f32 obj_look_y_max[] = { 30.0f, 20.0f };
static f32 obj_look_y_spd[] = { 0.5f, 2.5f };
xyz_t eye;
xyz_t pos;
xyz_t ground;
s16 move;
f32 moveX;
f32 moveY;
int obj_look_type = guide->obj_look_type;
s16 cur_angle;
f32 inter;
f32 sin;
f32 ground_y;
s16 angle;
move = guide->camera_move;
guide->camera_move += 0xE20;
angle = move;
angle += 0xE20;
moveX = cos_s(angle) * 0.1f;
angle = move;
angle += 0xE20;
moveY = sin_s(angle) * guide->camera_move_range;
if (guide->camera_move_y <= 0.0f && moveY >= 0.0f) {
s8 cnt = guide->camera_move_cnt;
cnt--;
if (cnt < 0) {
s8 set_cnt = guide->camera_move_set_counter;
set_cnt--;
if (set_cnt < 0) {
set_cnt = ARRAY_COUNT(mov_def_cnt) - 1;
}
guide->camera_move_set_counter = set_cnt;
cnt = mov_def_cnt[set_cnt];
guide->camera_move_range = 0.3f;
} else {
guide->camera_move_range *= 0.35f;
}
guide->camera_move_cnt = cnt;
}
guide->camera_move_y = moveY;
cur_angle = guide->camera_tilt_cur_angle;
chase_angle(&cur_angle, guide->camera_tilt_goal_angle, guide->camera_tilt_add);
guide->camera_tilt_cur_angle = cur_angle;
sin = sin_s(cur_angle);
/* Set camera eye pos */
eye.x = moveX + sin * 20.0f + 100.0f;
eye.y = moveY + sin * -5.0f + 80.0f;
eye.z = 400.0f;
/* Move NPC head to current target */
chase_f(&guide->npc_class.eye_y, obj_look_y_max[obj_look_type], obj_look_y_spd[obj_look_type] * 0.5f);
/* Set ground pos */
ground.x = guide->npc_class.draw.shadow_pos.x;
ground.z = guide->npc_class.draw.shadow_pos.z;
if (obj_look_type == aNGD_OBJ_LOOK_TYPE_TALK) {
/* Use the guide's NPC shadow position for Y */
ground_y = guide->npc_class.draw.shadow_pos.y;
} else {
/* Get the ground position for Y */
ground_y = mCoBG_GetBgY_OnlyCenter_FromWpos2(ground, 0.0f);
}
chase_f(&guide->obj_dist_ground, ground_y, 0.5f);
ground.y = guide->obj_dist_ground;
/* Set camera center pos */
if (guide->lock_camera_flag == TRUE) {
pos.x = ground.x;
pos.y = ground.y + guide->npc_class.eye_y;
pos.z = ground.z;
} else if (mDemo_Check(mDemo_TYPE_SPEAK, &guide->npc_class.actor_class) == TRUE) {
int morph_counter = guide->camera_morph_counter;
f32 r;
guide->camera_morph_counter = morph_counter - 1;
if ((morph_counter - 1) == 0) {
guide->lock_camera_flag = TRUE;
}
r = (40.0f - (f32)(morph_counter - 1)) / 40.0f;
inter = cKF_HermitCalc(r, 1.0f, 0.0f, 1.0f, 3.2f, 0.0f);
pos.x = (ground.x - 90.0f) * inter + 90.0f;
pos.y = ((ground.y + guide->npc_class.eye_y) - 80.0f) * inter + 80.0f;
pos.z = (ground.z - 280.0f) * inter + 280.0f;
} else {
/* Default position */
pos.x = 90.0f;
pos.y = 80.0f;
pos.z = 280.0f;
}
pos.x += moveX;
pos.y += moveY;
Camera2_change_priority(play, 0);
Camera2_request_main_lock(play, &pos, &eye, 40.0f, 0, 60.0f, 800.0f, 5);
}
static void aNGD_set_camera_eyes(NPC_GUIDE_ACTOR* guide) {
if (guide->camera_eyes_flag == TRUE) {
guide->npc_class.request.head_pos.x = 100.0f;
guide->npc_class.request.head_pos.y = guide->npc_class.actor_class.eye.position.y;
guide->npc_class.request.head_pos.z = 400.0f;
guide->npc_class.request.head_priority = 3;
guide->npc_class.request.head_type = 2;
}
}
static void aNGD_set_walk_spd(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
guide->npc_class.movement.max_speed = 1.0f;
guide->npc_class.movement.acceleration = 0.1f;
guide->npc_class.movement.deceleration = 0.2f;
}
static void aNGD_set_walk_spd2(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
guide->npc_class.movement.max_speed = 1.5f;
guide->npc_class.movement.acceleration = 0.15f;
guide->npc_class.movement.deceleration = 0.3f;
}
static void aNGD_set_stop_spd(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
guide->npc_class.actor_class.speed = 0.0f;
guide->npc_class.movement.max_speed = 0.0f;
guide->npc_class.movement.acceleration = 0.0f;
guide->npc_class.movement.deceleration = 0.0f;
}
static int aNGD_make_keitai(NPC_GUIDE_ACTOR* guide, GAME* game) {
int res = FALSE;
if (guide->npc_class.right_hand.item_actor_p == NULL) {
if (Common_Get(clip).tools_clip != NULL) {
ACTOR* keitai = Common_Get(clip).tools_clip->aTOL_birth_proc(TOOL_KEITAI, aTOL_ACTION_TAKEOUT,
&guide->npc_class.actor_class, game, -1, NULL);
if (keitai != NULL) {
guide->npc_class.right_hand.item_actor_p = keitai;
res = TRUE;
}
}
} else {
res = TRUE;
}
return res;
}
static int aNGD_chg_cond_keitai(NPC_GUIDE_ACTOR* guide, int cond) {
int res = FALSE;
if (Common_Get(clip).tools_clip != NULL) {
if (Common_Get(clip).tools_clip->aTOL_chg_request_mode_proc(
&guide->npc_class.actor_class, guide->npc_class.right_hand.item_actor_p, cond) == TRUE) {
res = TRUE;
}
}
return res;
}
static void aNGD_talk_demo_proc(ACTOR* actorx) {
if (mDemo_Check(mDemo_TYPE_SPEAK, actorx) == TRUE) {
Common_Get(clip).npc_clip->talk_demo_proc(actorx);
}
}
static void aNGD_check_talk_msg_no(NPC_GUIDE_ACTOR* guide) {
if (mDemo_Check(mDemo_TYPE_SPEAK, &guide->npc_class.actor_class) == TRUE) {
int msg_no = mMsg_GET_MSG_NUM();
int flags;
switch (msg_no) {
case 0x2AC9:
flags = (1 << 3);
break;
case 0x2ACD:
flags = (1 << 2);
break;
case 0x2ACF:
flags = (1 << 1);
break;
case 0x2AD3:
flags = (1 << 0);
break;
default:
flags = 0;
break;
}
guide->answer_flags |= flags;
}
}
static void aNGD_set_pl_face_type(NPC_GUIDE_ACTOR* guide) {
static int face_type_table[mPr_SEX_NUM][mPr_FACE_TYPE_NUM] = {
/* Male faces */
{
mPr_FACE_TYPE5,
mPr_FACE_TYPE6,
mPr_FACE_TYPE1,
mPr_FACE_TYPE4,
mPr_FACE_TYPE0,
mPr_FACE_TYPE2,
mPr_FACE_TYPE7,
mPr_FACE_TYPE3,
},
/* Female faces */
{
mPr_FACE_TYPE0,
mPr_FACE_TYPE5,
mPr_FACE_TYPE2,
mPr_FACE_TYPE6,
mPr_FACE_TYPE4,
mPr_FACE_TYPE7,
mPr_FACE_TYPE3,
mPr_FACE_TYPE1,
},
};
int answer_flags = guide->answer_flags;
int face_type;
if ((answer_flags & 1) == 0) {
/* Select a random face for the player */
face_type = RANDOM(mPr_FACE_TYPE_NUM);
} else {
/* Select a face based on choices */
face_type = face_type_table[Now_Private->gender][answer_flags >> 1];
}
Now_Private->face = face_type;
}
static void aNGD_calc_body_angl(NPC_GUIDE_ACTOR* guide, f32 pos_x, f32 pos_z) {
f32 dX = pos_x - guide->npc_class.actor_class.world.position.x;
f32 dZ = pos_z - guide->npc_class.actor_class.world.position.z;
s16 angl = atans_table(dZ, dX);
chase_angle(&guide->npc_class.actor_class.shape_info.rotation.y, angl, DEG2SHORT_ANGLE2(11.25f));
guide->npc_class.actor_class.world.angle.y = guide->npc_class.actor_class.shape_info.rotation.y;
}
static void aNGD_set_default_talk_info(void) {
mDemo_Set_camera(CAMERA2_PROCESS_NUM);
mDemo_Set_talk_change_player(FALSE);
mDemo_Set_use_zoom_sound(TRUE);
}
static void aNGD_enter(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
if (guide->npc_class.draw.main_animation_state == cKF_STATE_STOPPED) {
guide->camera_eyes_flag = TRUE;
aNGD_setupAction(guide, play, aNGD_ACTION_APPROACH);
} else if (cKF_FrameControl_passCheck_now(&guide->npc_class.draw.main_animation.keyframe.frame_control, 20.0f) ==
TRUE) {
TRAINDOOR_ACTOR* train_door = (TRAINDOOR_ACTOR*)guide->train_door_actor;
train_door->open_flag = TRUE;
}
}
static void aNGD_approach(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
if (guide->npc_class.actor_class.world.position.z >= 290.0f) {
guide->npc_class.actor_class.world.position.z = 290.0f;
aNGD_setupAction(guide, play, aNGD_ACTION_TALK_START_WAIT);
}
}
static void aNGD_set_talk_info_talk_start_wait(ACTOR* actorx) {
mDemo_Set_msg_num(0x2AC6);
aNGD_set_default_talk_info();
((NPC_GUIDE_ACTOR*)actorx)->obj_look_type = aNGD_OBJ_LOOK_TYPE_TALK;
}
static void aNGD_talk_start_wait(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
ACTOR* actorx = (ACTOR*)guide;
if (mDemo_Check(mDemo_TYPE_SPEAK, actorx) == TRUE) {
if (mDemo_Check_ListenAble() == FALSE &&
chase_angle(&actorx->shape_info.rotation.y, actorx->player_angle_y, 0x400) == TRUE) {
guide->camera_eyes_flag = FALSE;
aNGD_setupAction(guide, play, aNGD_ACTION_TIME_CHECK);
mDemo_Set_ListenAble();
}
} else {
mDemo_Request(mDemo_TYPE_SPEAK, actorx, &aNGD_set_talk_info_talk_start_wait);
}
}
static void aNGD_time_check(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
if (mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0:
aNGD_setupAction(guide, play, aNGD_ACTION_WAIT_PERMISSION);
break;
case mChoice_CHOICE1:
guide->next_action = aNGD_ACTION_TIME_MENU_OPEN_WAIT;
aNGD_setupAction(guide, play, aNGD_ACTION_SDON_AND_PB_WAIT);
break;
}
}
}
static void aNGD_sdon_and_pb_wait(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
u16 order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
if (order != 0 && mMsg_CHECK_MAINNORMALCONTINUE()) {
aNGD_setupAction(guide, play, guide->next_action);
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
}
static void aNGD_time_menu_open_wait(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
if (mMsg_CHECK_MAIN_WAIT() == TRUE) {
aNGD_setupAction(guide, play, guide->action + 1);
}
}
static void aNGD_time_menu_close_wait(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
if (play->submenu.open_flag == FALSE) {
aNGD_setupAction(guide, play, aNGD_ACTION_MSG_WIN_OPEN_WAIT);
}
}
static void aNGD_msg_win_open_wait(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
static int msg_no[] = { 0x2AE5, 0x2ACA, 0x2AE4 };
static int next_act_idx[] = {
aNGD_ACTION_CONFIRM_INPUT_DATA,
aNGD_ACTION_SEX_SELECT_WAIT,
aNGD_ACTION_CONFIRM_INPUT_DATA,
};
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
if (mMsg_Check_not_series_main_wait(msg_p) == TRUE) {
int idx = -1;
switch (guide->next_action) {
case aNGD_ACTION_TIME_MENU_CLOSE_WAIT:
idx = 0;
break;
case aNGD_ACTION_PNAME_MENU_CLOSE_WAIT:
idx = 1;
break;
case aNGD_ACTION_CNAME_MENU_CLOSE_WAIT:
idx = 2;
break;
}
if (idx >= 0) {
mMsg_Unset_LockContinue(msg_p);
mMsg_Set_continue_msg_num(msg_p, msg_no[idx]);
mMsg_Set_ForceNext(msg_p);
aNGD_setupAction(guide, play, next_act_idx[idx]);
}
}
}
static void aNGD_confirm_input_data(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
if (mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0:
switch (guide->next_action) {
case aNGD_ACTION_TIME_MENU_CLOSE_WAIT:
aNGD_setupAction(guide, play, aNGD_ACTION_WAIT_PERMISSION);
break;
case aNGD_ACTION_CNAME_MENU_CLOSE_WAIT:
aNGD_setupAction(guide, play, aNGD_ACTION_STANDUP_START_WAIT);
break;
}
break;
case mChoice_CHOICE1:
switch (guide->next_action) {
case aNGD_ACTION_TIME_MENU_CLOSE_WAIT:
guide->next_action = aNGD_ACTION_TIME_MENU_OPEN_WAIT;
break;
case aNGD_ACTION_CNAME_MENU_CLOSE_WAIT:
guide->next_action = aNGD_ACTION_CNAME_MENU_OPEN_WAIT;
break;
}
aNGD_setupAction(guide, play, aNGD_ACTION_SDON_AND_PB_WAIT);
break;
}
}
}
static void aNGD_wait_permission(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
if (mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
aNGD_setupAction(guide, play, aNGD_ACTION_SITDOWN);
}
}
static void aNGD_sitdown(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
guide->npc_class.actor_class.world.position.x = 100.0f;
guide->npc_class.actor_class.world.position.z = 280.0f;
guide->npc_class.actor_class.shape_info.rotation.y = 0;
/* Wait for the sit animation to finish before continuing */
if (guide->npc_class.draw.main_animation_state == cKF_STATE_STOPPED) {
mMsg_UNSET_LOCKCONTINUE();
guide->next_action = aNGD_ACTION_PNAME_MENU_OPEN_WAIT;
Common_Set(sunlight_flag, TRUE); // turn on the sunlight as we exit tunnel
/* Turn off echoes since we exited the tunnel */
sAdo_TrgSeEcho(FALSE);
sAdo_LevSeEcho(FALSE);
aNGD_setupAction(guide, play, aNGD_ACTION_SDON_AND_PB_WAIT);
}
}
static void aNGD_sex_select_wait(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
if (mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0: // male
case mChoice_CHOICE1: // female
aNGD_setupAction(guide, play, aNGD_ACTION_SEX_SELECT_WAIT2);
break;
case mChoice_CHOICE2: // 'That's not right'
guide->next_action = aNGD_ACTION_PNAME_MENU_OPEN_WAIT;
aNGD_setupAction(guide, play, aNGD_ACTION_SDON_AND_PB_WAIT);
break;
}
}
}
static void aNGD_sex_select_wait2(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
if (order != 0 && mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0: // male
switch (order) {
case 1: // That's right
Now_Private->gender = mPr_SEX_MALE;
break;
case 2: // I'm not a boy
Now_Private->gender = mPr_SEX_FEMALE;
break;
}
guide->next_action = aNGD_ACTION_CNAME_MENU_OPEN_WAIT;
aNGD_setupAction(guide, play, aNGD_ACTION_SDON_AND_PB_WAIT);
break;
case mChoice_CHOICE1: // female
switch (order) {
case 1: // That's right
Now_Private->gender = mPr_SEX_FEMALE;
break;
case 2: // I'm not a girl
Now_Private->gender = mPr_SEX_MALE;
break;
}
aNGD_setupAction(guide, play, aNGD_ACTION_SEX_SELECT_AFTER);
break;
}
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
}
static void aNGD_sex_select_after(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
u16 order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
if (order != 0 && mMsg_Check_MainNormalContinue(msg_p)) {
mMsg_Set_continue_msg_num(msg_p, 0x2AD8);
mMsg_Set_ForceNext(msg_p);
guide->next_action = aNGD_ACTION_CNAME_MENU_OPEN_WAIT;
aNGD_setupAction(guide, play, aNGD_ACTION_SDON_AND_PB_WAIT);
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
}
static void aNGD_standup_start_wait(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
/* Wait for guide to stop speaking to us */
if (mDemo_Check(mDemo_TYPE_SPEAK, &guide->npc_class.actor_class) == FALSE) {
guide->obj_look_type = aNGD_OBJ_LOOK_TYPE_NORMAL;
aNGD_setupAction(guide, play, aNGD_ACTION_STANDUP);
}
}
static void aNGD_standup(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
/* Wait for animation to finish */
if (guide->npc_class.draw.main_animation_state == cKF_STATE_STOPPED) {
aNGD_setupAction(guide, play, guide->next_action);
}
}
static void aNGD_move_ready(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
guide->npc_class.actor_class.world.position.x = 100.0f;
guide->npc_class.actor_class.world.position.z = 300.0f;
aNGD_setupAction(guide, play, aNGD_ACTION_MOVE_TO_AISLE);
}
static void aNGD_move_to_aisle(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
aNGD_calc_body_angl(guide, 140.0f, 290.0f);
if (guide->npc_class.actor_class.world.position.x > 140.0f) {
aNGD_setupAction(guide, play, aNGD_ACTION_MOVE_TO_DOOR);
}
}
static void aNGD_move_to_door(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
aNGD_calc_body_angl(guide, 140.0f, 130.0f);
/* Check if we reached the door */
if (guide->npc_class.actor_class.world.position.z < 130.0f) {
aNGD_setupAction(guide, play, aNGD_ACTION_MOVE_TO_DECK);
}
/* Check if we should start rotating */
if (guide->npc_class.draw.shadow_pos.z < 140.0f) {
guide->camera_tilt_goal_angle = DEG2SHORT_ANGLE2(90.0f);
guide->camera_tilt_add = DEG2SHORT_ANGLE2(2.8125f);
}
}
static void aNGD_move_to_deck(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
if (cKF_FrameControl_passCheck_now(&guide->npc_class.draw.main_animation.keyframe.frame_control, 9.0f) == TRUE) {
TRAINDOOR_ACTOR* train_door = (TRAINDOOR_ACTOR*)guide->train_door_actor;
train_door->open_flag = TRUE;
}
/* Reuse standup state to wait for animation to finish */
aNGD_standup(guide, play);
}
static void aNGD_set_talk_info_keitai_on(ACTOR* actorx) {
mDemo_Set_msg_num(0x2AD0);
aNGD_set_default_talk_info();
}
static void aNGD_keitai_on(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
static f32 anmSpd[] = { 0.0f, 0.5f };
int idx = aNGD_make_keitai(guide, &play->game);
guide->npc_class.draw.main_animation.keyframe.frame_control.speed = anmSpd[idx];
if (idx != 0) {
if (mDemo_Check(mDemo_TYPE_SPEAK, (ACTOR*)guide) == TRUE) {
if (mDemo_Check_ListenAble() == FALSE) {
mDemo_Set_ListenAble();
}
} else {
/* Request to start speaking */
mDemo_Request(mDemo_TYPE_SPEAK, (ACTOR*)guide, &aNGD_set_talk_info_keitai_on);
}
}
/* Wait for animation to finish */
if (guide->npc_class.draw.main_animation_state == cKF_STATE_STOPPED) {
aNGD_setupAction(guide, play, aNGD_ACTION_KEITAI_TALK);
}
}
static void aNGD_keitai_talk(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
if (mDemo_Check(mDemo_TYPE_SPEAK, &guide->npc_class.actor_class) == FALSE) {
aNGD_setupAction(guide, play, aNGD_ACTION_KEITAI_OFF);
} else if (guide->npc_class.draw.main_animation_state == cKF_STATE_STOPPED) {
Common_Get(clip).npc_clip->animation_init_proc(&guide->npc_class.actor_class, aNPC_ANIM_KEITAI_TALK2, TRUE);
}
}
static void aNGD_open_door(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
chase_angle(&guide->npc_class.actor_class.shape_info.rotation.y, DEG2SHORT_ANGLE2(-180.0f),
DEG2SHORT_ANGLE2(0.703125f));
if (cKF_FrameControl_passCheck_now(&guide->npc_class.draw.main_animation.keyframe.frame_control, 22.0f) == TRUE) {
TRAINDOOR_ACTOR* train_door = (TRAINDOOR_ACTOR*)guide->train_door_actor;
train_door->open_flag = TRUE;
if (guide->npc_class.draw.shadow_pos.z < 140.0f) {
guide->camera_tilt_goal_angle = 0;
guide->camera_tilt_add = 0x600;
}
}
/* Reuse standup state to wait for animation to finish */
aNGD_standup(guide, play);
}
static void aNGD_return_approach(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
guide->npc_class.actor_class.world.position.x = 140.0f;
guide->npc_class.actor_class.world.angle.y = 0;
guide->npc_class.actor_class.shape_info.rotation.y = 0;
if (guide->npc_class.actor_class.world.position.z > 290.0f) {
aNGD_setupAction(guide, play, aNGD_ACTION_LAST_TALK_START_WAIT);
}
}
static void aNGD_set_talk_info_last_talk_start_wait(ACTOR* actorx) {
mDemo_Set_msg_num(0x2AD1);
aNGD_set_default_talk_info();
((NPC_GUIDE_ACTOR*)actorx)->obj_look_type = aNGD_OBJ_LOOK_TYPE_TALK;
}
static void aNGD_last_talk_start_wait(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
ACTOR* actorx = (ACTOR*)guide;
if (mDemo_Check(mDemo_TYPE_SPEAK, actorx) == TRUE) {
if (mDemo_Check_ListenAble() == FALSE &&
chase_angle(&actorx->shape_info.rotation.y, actorx->player_angle_y, 0x400) == TRUE) {
guide->camera_eyes_flag = FALSE;
aNGD_setupAction(guide, play, aNGD_ACTION_SITDOWN2_START_WAIT);
mDemo_Set_ListenAble();
}
} else {
mDemo_Request(mDemo_TYPE_SPEAK, actorx, &aNGD_set_talk_info_last_talk_start_wait);
}
}
static void aNGD_sitdown2_start_wait(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
u16 order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
if (order != 0) {
aNGD_setupAction(guide, play, aNGD_ACTION_SITDOWN2);
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
}
static void aNGD_sitdown2(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
guide->npc_class.actor_class.world.position.x = 100.0f;
guide->npc_class.actor_class.world.position.z = 280.0f;
guide->npc_class.actor_class.shape_info.rotation.y = 0;
/* Wait for animation to finish */
aNGD_standup(guide, play);
}
static void aNGD_last_talk_end_wait(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
if (mDemo_Check(mDemo_TYPE_SPEAK, &guide->npc_class.actor_class) == FALSE) {
aNGD_setupAction(guide, play, aNGD_ACTION_SCENE_CHANGE_WAIT);
}
}
/* Init procs */
static void aNGD_time_menu_open_wait_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
mMsg_Set_LockContinue(msg_p);
mMsg_request_main_disappear_wait_type1(msg_p);
guide->next_action = aNGD_ACTION_TIME_MENU_CLOSE_WAIT;
}
static void aNGD_time_menu_close_wait_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
Submenu* submenu = &play->submenu;
switch (guide->next_action) {
case aNGD_ACTION_TIME_MENU_CLOSE_WAIT:
mSM_open_submenu(submenu, mSM_OVL_TIMEIN, mTI_OVL_OPEN_INITIAL, 0);
break;
case aNGD_ACTION_PNAME_MENU_CLOSE_WAIT:
mSM_open_submenu(submenu, mSM_OVL_LEDIT, mLE_TYPE_PLAYER_NAME, 0);
break;
case aNGD_ACTION_CNAME_MENU_CLOSE_WAIT:
mSM_open_submenu(submenu, mSM_OVL_LEDIT, mLE_TYPE_COUNTRY_NAME, 0);
break;
}
}
static void aNGD_msg_win_open_wait_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
mMsg_REQUEST_MAIN_APPEAR_WAIT_TYPE1();
}
static void aNGD_sitdown_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
mMsg_SET_LOCKCONTINUE();
}
static void aNGD_pname_menu_open_wait_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
mMsg_Set_LockContinue(msg_p);
mMsg_request_main_disappear_wait_type1(msg_p);
guide->next_action = aNGD_ACTION_PNAME_MENU_CLOSE_WAIT;
}
static void aNGD_cname_menu_open_wait_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
mMsg_Set_LockContinue(msg_p);
mMsg_request_main_disappear_wait_type1(msg_p);
guide->next_action = aNGD_ACTION_CNAME_MENU_CLOSE_WAIT;
}
static void aNGD_standup_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
guide->next_action = aNGD_ACTION_MOVE_READY;
}
static void aNGD_move_ready_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
guide->npc_class.draw.main_animation.keyframe.morph_counter = 0.0f;
}
static void aNGD_move_to_aisle_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
aNGD_set_walk_spd2(guide, play);
}
static void aNGD_move_to_deck_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
aNGD_set_stop_spd(guide, play);
guide->npc_class.actor_class.world.position.x = 140.0f;
guide->npc_class.actor_class.world.position.z = 130.0f;
guide->next_action = aNGD_ACTION_KEITAI_ON;
}
static void aNGD_keitai_off_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
aNGD_chg_cond_keitai(guide, aTOL_ACTION_PUTAWAY);
guide->next_action = aNGD_ACTION_OPEN_DOOR;
}
static void aNGD_open_door_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
guide->next_action = aNGD_ACTION_RETURN_APPROACH;
}
static void aNGD_return_approach_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
guide->camera_eyes_flag = TRUE;
aNGD_set_walk_spd2(guide, play);
guide->npc_class.draw.main_animation.keyframe.morph_counter = 0.0f;
}
static void aNGD_sitdown2_start_wait_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
static void aNGD_sitdown2_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
guide->npc_class.draw.main_animation.keyframe.morph_counter = 0.0f;
guide->next_action = aNGD_ACTION_LAST_TALK_END_WAIT;
}
static void aNGD_last_talk_end_wait_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
aNGD_chg_cond_keitai(guide, aTOL_ACTION_DESTRUCT);
guide->npc_class.right_hand.item_actor_p = NULL;
}
static void aNGD_scene_change_wait_init(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play) {
u8 term;
int town_day;
/* Init next scene transition */
goto_next_scene(play, 0, 1);
play->fb_wipe_type = 3;
Common_Get(transition).wipe_type = 4;
/* Clear plant growth renew time */
Save_Set(all_grow_renew_time, mTM_rtcTime_clear_code);
/* Update player ID town info */
if (Now_Private != NULL) {
mLd_CopyLandName(Now_Private->player_ID.land_name, Save_Get(land_info).name);
}
/* Init island */
bcopy(Save_GetPointer(land_info), &Save_Get(island).landinfo, sizeof(mLd_land_info_c)); // Copy the town's land info
mNpc_DecideIslandNpc(&Save_Get(island).animal); // Pick islander
/* Update some renew time values to current rtc time */
lbRTC_TimeCopy(Save_GetPointer(last_grow_time), Common_GetPointer(time.rtc_time));
mTM_set_renew_time(Save_GetPointer(renew_time), Common_GetPointer(time.rtc_time));
mTM_set_season(); // initialize the season
/* Initialize first Stalk Market info */
Kabu_decide_price_schedule();
/* Init Post Office */
mPO_post_office_init();
/* Set insect term info */
Save_Set(insect_term, Common_Get(time.rtc_time.month));
Save_Set(insect_term_transition_offset, RANDOM(6));
/* Set fish term info */
term = Common_Get(time.rtc_time.month) * 2;
if (Common_Get(time.rtc_time.day) > 15) {
term++;
}
Save_Set(gyoei_term, term);
Save_Set(gyoei_term_transition_offset, RANDOM(6));
/* Decide Town Day date */
town_day = 1 + RANDOM(30);
if (town_day >= 4) {
town_day++; // add one to prevent conflict with Fireworks Festival (4th of July)
}
Save_Set(town_day, town_day);
mSP_ShopGameStartCt(NULL);
mNtc_SetInitData();
mPr_SetNowPrivateCloth();
mEv_SetFirstJob();
mEv_SetFirstIntro();
mEnv_DecideWeather_FirstGameStart();
mCD_calendar_clear(-1);
mCD_calendar_wellcome_on();
mNpc_SetParentNameAllAnimal();
aNGD_set_pl_face_type(guide);
Common_Set(submenu_disabled, TRUE);
mRmTp_SetDefaultLightSwitchData(1);
mBGMPsComp_make_ps_wipe(0x41C2);
mBGMPsComp_scene_mode(18);
}
typedef void (*aNGD_INIT_PROC)(NPC_GUIDE_ACTOR*, GAME_PLAY*);
static void aNGD_init_proc(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play, int action) {
static aNGD_INIT_PROC init_proc[] = {
(aNGD_INIT_PROC)&none_proc1,
&aNGD_set_walk_spd,
&aNGD_set_stop_spd,
(aNGD_INIT_PROC)&none_proc1,
(aNGD_INIT_PROC)&none_proc1,
&aNGD_time_menu_open_wait_init,
&aNGD_time_menu_close_wait_init,
&aNGD_msg_win_open_wait_init,
(aNGD_INIT_PROC)&none_proc1,
(aNGD_INIT_PROC)&none_proc1,
&aNGD_sitdown_init,
&aNGD_pname_menu_open_wait_init,
&aNGD_time_menu_close_wait_init,
(aNGD_INIT_PROC)&none_proc1,
(aNGD_INIT_PROC)&none_proc1,
(aNGD_INIT_PROC)&none_proc1,
&aNGD_cname_menu_open_wait_init,
&aNGD_time_menu_close_wait_init,
(aNGD_INIT_PROC)&none_proc1,
&aNGD_standup_init,
&aNGD_move_ready_init,
&aNGD_move_to_aisle_init,
(aNGD_INIT_PROC)&none_proc1,
&aNGD_move_to_deck_init,
(aNGD_INIT_PROC)&none_proc1,
(aNGD_INIT_PROC)&none_proc1,
&aNGD_keitai_off_init,
&aNGD_open_door_init,
&aNGD_return_approach_init,
&aNGD_set_stop_spd,
&aNGD_sitdown2_start_wait_init,
&aNGD_sitdown2_init,
&aNGD_last_talk_end_wait_init,
&aNGD_scene_change_wait_init,
};
(*init_proc[action])(guide, play);
}
static void aNGD_setupAction(NPC_GUIDE_ACTOR* guide, GAME_PLAY* play, int action) {
static aNGD_PROC process[] = {
&aNGD_enter,
&aNGD_approach,
&aNGD_talk_start_wait,
&aNGD_time_check,
&aNGD_sdon_and_pb_wait,
&aNGD_time_menu_open_wait,
&aNGD_time_menu_close_wait,
&aNGD_msg_win_open_wait,
&aNGD_confirm_input_data,
&aNGD_wait_permission,
&aNGD_sitdown,
&aNGD_time_menu_open_wait,
&aNGD_time_menu_close_wait,
&aNGD_sex_select_wait,
&aNGD_sex_select_wait2,
&aNGD_sex_select_after,
&aNGD_time_menu_open_wait,
&aNGD_time_menu_close_wait,
&aNGD_standup_start_wait,
&aNGD_standup,
&aNGD_move_ready,
&aNGD_move_to_aisle,
&aNGD_move_to_door,
&aNGD_move_to_deck,
&aNGD_keitai_on,
&aNGD_keitai_talk,
&aNGD_standup,
&aNGD_open_door,
&aNGD_return_approach,
&aNGD_last_talk_start_wait,
&aNGD_sitdown2_start_wait,
&aNGD_sitdown2,
&aNGD_last_talk_end_wait,
(aNGD_PROC)&none_proc1,
};
guide->action = action;
guide->proc = process[action];
aNGD_set_animation(guide, action);
aNGD_init_proc(guide, play, action);
}
static void aNGD_actor_move(ACTOR* actorx, GAME* game) {
NPC_GUIDE_ACTOR* guide = (NPC_GUIDE_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
Common_Get(clip).npc_clip->move_before_proc(actorx, game);
aNGD_talk_demo_proc(actorx);
aNGD_check_talk_msg_no(guide);
(*guide->proc)(guide, play);
Common_Get(clip).npc_clip->move_after_proc(actorx, game);
aNGD_set_camera(guide, play);
aNGD_set_camera_eyes(guide);
mSC_change_player_freeze(play);
}
+162
View File
@@ -0,0 +1,162 @@
#include "ac_npc_p_sel.h"
#include "m_config.h"
#include "m_common_data.h"
#include "m_player_lib.h"
#include "m_soncho.h"
#include "m_play.h"
#include "m_card.h"
#include "m_bgm.h"
#include "m_choice.h"
#include "m_msg.h"
#include "m_vibctl.h"
#include "libultra/libultra.h"
#include "dolphin/os/OSRtc.h"
enum {
aNPS_TALK_CHK_SETUP_SOUND,
aNPS_TALK_SETUP_SOUND,
aNPS_TALK_SETUP_VOICE,
aNPS_TALK_CONFIRM_INPUT_DATA,
aNPS_TALK_CONFIRM_INPUT_DATA2,
aNPS_TALK_SETUP_YURE,
aNPS_TALK_WAIT,
aNPS_TALK_NUM
};
typedef void (*aNPS_THINK_PROC)(NPC_ACTOR*, GAME_PLAY*);
static void aNPS_actor_ct(ACTOR* actorx, GAME* game);
static void aNPS_actor_dt(ACTOR* actorx, GAME* game);
static void aNPS_actor_init(ACTOR* actorx, GAME* game);
static void aNPS_actor_save(ACTOR* actorx, GAME* game);
static void aNPS_actor_move(ACTOR* actorx, GAME* game);
static void aNPS_actor_draw(ACTOR* actorx, GAME* game);
static void aNPS_talk_request(ACTOR* actorx, GAME* game);
static void aNPS_change_talk_proc(NPC_P_SEL_ACTOR* p_sel, int talk_idx);
static int aNPS_talk_init(ACTOR* actorx, GAME* game);
static int aNPS_talk_end_chk(ACTOR* actorx, GAME* game);
static void aNPS_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type);
// clang-format off
ACTOR_PROFILE Npc_P_Sel_Profile = {
mAc_PROFILE_NPC_P_SEL,
ACTOR_PART_NPC,
ACTOR_STATE_NONE,
SP_NPC_P_SEL,
ACTOR_OBJ_BANK_KEEP,
sizeof(NPC_P_SEL_ACTOR),
&aNPS_actor_ct,
&aNPS_actor_dt,
&aNPS_actor_init,
mActor_NONE_PROC1,
&aNPS_actor_save,
};
// clang-format on
static u8 aNPS_sound_mode[] = { Config_SOUND_MODE_STEREO, Config_SOUND_MODE_MONO, Config_SOUND_MODE_HEADPHONES };
static u8 aNPS_voice_mode[] = { Config_VOICE_MODE_ANIMALESE, Config_VOICE_MODE_CLICK, Config_VOICE_MODE_SILENT };
static void aNPS_actor_ct(ACTOR* actorx, GAME* game) {
// clang-format off
static aNPC_ct_data_c ct_data = {
&aNPS_actor_move,
&aNPS_actor_draw,
5,
(aNPC_TALK_REQUEST_PROC)&none_proc1,
&aNPS_talk_init,
&aNPS_talk_end_chk,
0,
};
// clang-format off
GAME_PLAY* play = (GAME_PLAY*)game;
NPC_P_SEL_ACTOR* p_sel = (NPC_P_SEL_ACTOR*)actorx;
PLAYER_ACTOR* player;
xyz_t center;
xyz_t eye;
if (CLIP(npc_clip)->birth_check_proc(actorx, game) == TRUE) {
p_sel->npc_class.schedule.schedule_proc = &aNPS_schedule_proc;
CLIP(npc_clip)->ct_proc(actorx, game, &ct_data);
actorx->status_data.weight = MASSTYPE_IMMOVABLE;
mPlib_request_main_demo_wait_type1(game, FALSE, NULL);
player = GET_PLAYER_ACTOR(play);
if (player != NULL) {
player->actor_class.state_bitfield |= ACTOR_STATE_INVISIBLE;
}
center.x = 100.0f;
center.y = 60.0f;
center.z = 60.0f;
eye.x = 100.0f;
eye.y = 130.0f;
eye.z = 210.0f;
Camera2_change_priority(play, 0);
Camera2_request_main_lock(play, &center, &eye, 40.0f, 0, 100.0f, 400.0f, 5);
if (OSGetSoundMode() == OS_SOUND_MODE_MONO) {
Save_Get(config).sound_mode = Config_SOUND_MODE_MONO;
} else {
Save_Get(config).sound_mode = Config_SOUND_MODE_STEREO;
}
sAdo_SetOutMode(aNPS_sound_mode[Save_Get(config).sound_mode]);
Save_Get(config).voice_mode = Config_VOICE_MODE_ANIMALESE;
sAdo_SetVoiceMode(aNPS_voice_mode[Save_Get(config).voice_mode]);
p_sel->npc_class.condition_info.hide_request = FALSE;
p_sel->npc_class.talk_info.default_act = aNPC_ACT_INTO_HOUSE;
}
}
static void aNPS_actor_save(ACTOR* actorx, GAME* game) {
CLIP(npc_clip)->save_proc(actorx, game);
}
static void aNPS_actor_dt(ACTOR* actorx, GAME* game) {
CLIP(npc_clip)->dt_proc(actorx, game);
}
static void aNPS_actor_init(ACTOR* actorx, GAME* game) {
CLIP(npc_clip)->init_proc(actorx, game);
}
static void aNPS_actor_move(ACTOR* actorx, GAME* game) {
NPC_P_SEL_ACTOR* p_sel;
cKF_FrameControl_c* fc_p;
f32 speed;
u8 arm_flag;
StaffRollInfo_c staffroll_info;
p_sel = (NPC_P_SEL_ACTOR*)actorx;
fc_p = &p_sel->npc_class.draw.main_animation.keyframe.frame_control;
speed = 0.5f;
arm_flag = TRUE;
if (p_sel->npc_class.draw.animation_id == aNPC_ANIM_4HAKU_E1) {
sAdos_GetStaffRollInfo(&staffroll_info);
if (staffroll_info.staffroll_part != STAFFROLL_PART_FINISH) {
speed = 0.0f;
arm_flag = FALSE;
fc_p->current_frame = 1.0f + 64.0f * (f32)staffroll_info.percent;
}
}
fc_p->speed = speed;
sAdos_TTKK_ARM(arm_flag);
CLIP(npc_clip)->move_proc(actorx, game);
mSC_change_player_freeze((GAME_PLAY*)game); // TODO: mSC_change_player_freeze almost certainly takes a GAME*
}
static void aNPS_actor_draw(ACTOR* actorx, GAME* game) {
CLIP(npc_clip)->draw_proc(actorx, game);
}
#include "../src/actor/ac_npc_p_sel_schedule.c_inc"
#include "../src/actor/ac_npc_p_sel_talk.c_inc"
+88
View File
@@ -0,0 +1,88 @@
static int aNPS_setup_game_start(GAME_PLAY* play) {
static Door_data_c door_data = {
SCENE_START_DEMO, mSc_DIRECT_NORTH, 0, 0, { 120, 0, 340 }, EMPTY_NO, 3, { 0, 0, 0 }
};
s32 chan;
int res = FALSE;
if (mCD_InitGameStart_bg(0, -1, 0, &chan) == 0) {
goto_other_scene(play, &door_data, TRUE);
Common_Set(transition.wipe_type, 3);
Common_Set(map_flag, FALSE);
res = TRUE;
}
return res;
}
static void aNPS_think_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
NPC_P_SEL_ACTOR* p_sel = (NPC_P_SEL_ACTOR*)nactorx;
u32 alpha;
if (!p_sel->talk_end_flag) {
if (p_sel->strum_timer == 0) {
nactorx->talk_info.talk_request_proc = &aNPS_talk_request;
} else {
p_sel->strum_timer--;
}
} else {
if (p_sel->strum_timer == 0) {
if (aNPS_setup_game_start(play) == TRUE) {
p_sel->strum_timer = -1;
play->fade_color_value.c.a = 255;
}
} else if (p_sel->strum_timer > 0) {
if (p_sel->strum_timer < 70) {
alpha = 255 * (1.0f - p_sel->strum_timer / 70.0f);
play->fade_color_value.c.a = (u8)alpha;
}
p_sel->strum_timer--;
}
}
if (p_sel->bgm_stop_timer == 0) {
mBGMPsComp_make_ps_wipe(0x421C);
p_sel->bgm_stop_timer = -1;
} else if (p_sel->bgm_stop_timer > 0) {
p_sel->bgm_stop_timer--;
}
}
static void aNPS_think_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
NPC_P_SEL_ACTOR* p_sel = (NPC_P_SEL_ACTOR*)nactorx;
nactorx->request.act_priority = 4;
nactorx->request.act_idx = aNPC_ACT_TALK;
nactorx->request.act_type = aNPC_ACT_TYPE_DEFAULT;
}
static void aNPS_think_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) {
static aNPS_THINK_PROC think_proc[] = { &aNPS_think_init_proc, &aNPS_think_main_proc };
(*think_proc[type])(nactorx, play);
}
static void aNPS_schedule_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
NPC_P_SEL_ACTOR* p_sel = (NPC_P_SEL_ACTOR*)nactorx;
nactorx->draw._5BE = 1;
nactorx->think.think_proc = &aNPS_think_proc;
nactorx->talk_info.default_animation = aNPC_ANIM_4HAKU_E1;
p_sel->strum_timer = 440;
p_sel->bgm_stop_timer = -1;
CLIP(npc_clip)->think_proc(nactorx, play, aNPC_THINK_IN_BLOCK, 0);
}
static void aNPS_schedule_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
if (CLIP(npc_clip)->think_proc(nactorx, play, -1, 1) == 0) {
CLIP(npc_clip)->think_proc(nactorx, play, -1, 2);
}
}
static void aNPS_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) {
static aNPC_SUB_PROC sche_proc[] = { &aNPS_schedule_init_proc, &aNPS_schedule_main_proc };
(*sche_proc[type])(nactorx, play);
}
+236
View File
@@ -0,0 +1,236 @@
static int aNPS_setup_sound_option(void) {
static u8 sound_mode[] = { Config_SOUND_MODE_STEREO, Config_SOUND_MODE_MONO, Config_SOUND_MODE_HEADPHONES };
int order;
int res;
int idx;
order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
res = FALSE;
if (order != 0) {
idx = 0;
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0:
idx = 0;
break;
case mChoice_CHOICE1:
idx = 1;
break;
case mChoice_CHOICE2:
idx = 2;
break;
}
OSSetSoundMode(sound_mode[idx] == Config_SOUND_MODE_MONO ? OS_SOUND_MODE_MONO : OS_SOUND_MODE_STEREO);
Save_Get(config).sound_mode = sound_mode[idx];
sAdo_SetOutMode(aNPS_sound_mode[idx]);
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
res = TRUE;
}
return res;
}
static int aNPS_setup_voice_option(void) {
static u8 voice_mode[] = { Config_VOICE_MODE_ANIMALESE, Config_VOICE_MODE_CLICK, Config_VOICE_MODE_SILENT };
int order;
int res;
int idx;
order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
res = FALSE;
if (order != 0) {
idx = 0;
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0:
idx = 0;
break;
case mChoice_CHOICE1:
idx = 1;
break;
case mChoice_CHOICE2:
idx = 2;
break;
}
Save_Get(config).voice_mode = voice_mode[idx];
sAdo_SetVoiceMode(aNPS_voice_mode[idx]);
mMsg_sound_spec_change_voice_force(mMsg_Get_base_window_p());
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
res = TRUE;
}
return res;
}
static int aNPS_setup_yure_option(void) {
int order;
int res;
int disabled;
order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
res = FALSE;
if (order != 0) {
disabled = TRUE;
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0:
disabled = FALSE;
mVibctl_entry(75, mVibctl_VIB_PROG_NON, mVibctl_VIB_PROG_FFF, mVibctl_VIB_PROG_P, 0, 16, 45, 0.0f);
break;
case mChoice_CHOICE1:
disabled = TRUE;
break;
}
Save_Get(config).vibration_disabled = disabled;
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
res = TRUE;
}
return res;
}
static void aNPS_chk_setup_sound(NPC_P_SEL_ACTOR* p_sel, GAME_PLAY* play) {
if (mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
int next_talk_idx = -1;
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0:
next_talk_idx = aNPS_TALK_WAIT;
break;
case mChoice_CHOICE1:
next_talk_idx = aNPS_TALK_SETUP_YURE;
p_sel->next_talk_idx = aNPS_TALK_CONFIRM_INPUT_DATA;
break;
}
if (next_talk_idx != -1) {
aNPS_change_talk_proc(p_sel, next_talk_idx);
}
}
}
static void aNPS_setup_sound(NPC_P_SEL_ACTOR* p_sel, GAME_PLAY* play) {
if (aNPS_setup_sound_option() == TRUE) {
aNPS_change_talk_proc(p_sel, aNPS_TALK_SETUP_VOICE);
}
}
static void aNPS_setup_yure(NPC_P_SEL_ACTOR* p_sel, GAME_PLAY* play) {
if (aNPS_setup_yure_option() == TRUE) {
aNPS_change_talk_proc(p_sel, aNPS_TALK_SETUP_SOUND);
}
}
static void aNPS_setup_voice(NPC_P_SEL_ACTOR* p_sel, GAME_PLAY* play) {
if (aNPS_setup_voice_option() == TRUE) {
aNPS_change_talk_proc(p_sel, p_sel->next_talk_idx);
}
}
static void aNPS_confirm_input_data(NPC_P_SEL_ACTOR* p_sel, GAME_PLAY* play) {
if (mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0:
aNPS_change_talk_proc(p_sel, aNPS_TALK_CONFIRM_INPUT_DATA2);
break;
default:
aNPS_change_talk_proc(p_sel, aNPS_TALK_SETUP_VOICE);
break;
}
}
}
static void aNPS_confirm_input_data2(NPC_P_SEL_ACTOR* p_sel, GAME_PLAY* play) {
if (mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0:
aNPS_change_talk_proc(p_sel, aNPS_TALK_WAIT);
break;
default:
aNPS_change_talk_proc(p_sel, aNPS_TALK_SETUP_YURE);
break;
}
}
}
static void aNPS_change_talk_proc(NPC_P_SEL_ACTOR* p_sel, int talk_idx) {
static aNPS_TALK_PROC process[] = {
&aNPS_chk_setup_sound, &aNPS_setup_sound, &aNPS_setup_voice, &aNPS_confirm_input_data,
&aNPS_confirm_input_data2, &aNPS_setup_yure, (aNPS_TALK_PROC)&none_proc1,
};
p_sel->talk_idx = talk_idx;
p_sel->talk_proc = process[talk_idx];
}
static void aNPS_set_talk_info_talk_request(ACTOR* actorx) {
int msg_no = !mFRm_CheckSaveData() ? 0x09C7 : 0x09CA;
mDemo_Set_msg_num(msg_no);
mDemo_Set_camera(CAMERA2_PROCESS_NORMAL);
}
static void aNPS_talk_request(ACTOR* actorx, GAME* game) {
mDemo_Request(mDemo_TYPE_SPEAK, actorx, &aNPS_set_talk_info_talk_request);
}
static int aNPS_talk_init(ACTOR* actorx, GAME* game) {
NPC_P_SEL_ACTOR* p_sel = (NPC_P_SEL_ACTOR*)actorx;
mDemo_Set_ListenAble();
aNPS_change_talk_proc(p_sel, aNPS_TALK_CHK_SETUP_SOUND);
p_sel->npc_class.talk_info.talk_request_proc = (aNPC_TALK_REQUEST_PROC)&none_proc1;
mMsg_SET_IDLING_REQ();
return TRUE;
}
static int aNPS_talk_end_chk(ACTOR* actorx, GAME* game) {
NPC_P_SEL_ACTOR* p_sel = (NPC_P_SEL_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
int res = FALSE;
(*p_sel->talk_proc)(p_sel, play);
if (mMsg_Check_idling_now(msg_p) == TRUE) {
mMsg_request_main_disappear_wait_type1(msg_p);
p_sel->strum_timer = 150;
p_sel->bgm_stop_timer = 80;
bzero(&play->fade_color_value, sizeof(rgba8888));
aNPS_think_init_proc(&p_sel->npc_class, play);
p_sel->talk_end_flag = TRUE;
res = TRUE;
} else {
int silent_counter = p_sel->silent_counter;
if (mMsg_Check_MainNormal(msg_p) == TRUE || mChoice_CHECK_MAIN_NORMAL() == TRUE) {
silent_counter++;
if (silent_counter > 600) {
silent_counter = 600;
}
} else {
silent_counter = 0;
}
if (mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 0) == 0) {
if (silent_counter >= 600) {
if (p_sel->npc_class.draw.animation_id != aNPC_ANIM_4HAKU_E1) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 0, 255);
}
} else {
if (p_sel->npc_class.draw.animation_id == aNPC_ANIM_4HAKU_E1) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 0, 253);
}
}
}
p_sel->silent_counter = silent_counter;
}
return res;
}
+162
View File
@@ -0,0 +1,162 @@
#include "ac_npc_rcn_guide.h"
#include "m_play.h"
#include "m_name_table.h"
#include "libultra/libultra.h"
#include "m_common_data.h"
#include "m_player_lib.h"
#include "m_bgm.h"
#include "m_msg.h"
#include "m_font.h"
#include "m_house.h"
#include "ac_intro_demo.h"
/* sizeof(aNRG_talk_data_c) == 0x0C */
typedef struct rcn_guide_talk_data_s {
/* 0x00 */ int msg_no;
/* 0x04 */ u8 turn_flag;
/* 0x05 */ u8 camera_type;
/* 0x06 */ u8 melody_flag;
/* 0x08 */ aNRG_TALK_PROC talk_proc;
} aNRG_talk_data_c;
enum {
aNRC_THINK_CALL,
aNRC_THINK_APPROACH,
aNRG_THINK_INTRODUCE,
aNRC_THINK_TURN,
aNRC_THINK_TAKE_WITH,
aNRC_THINK_EXPLAIN,
aNRC_THINK_DECIDE_HOUSE_WAIT,
aNRC_THINK_STOP_WADE,
aNRC_THINK_BEFORE_OPEN_DOOR_TALK,
aNRC_THINK_BEFORE_OPEN_DOOR_TALK2,
aNRC_THINK_ENTER_WAIT,
aNRC_THINK_RESTART_WAIT,
aNRC_THINK_RESTART_TALK,
aNRC_THINK_DECIDE_HOUSE,
aNRC_THINK_EXIT_TURN,
aNRC_THINK_EXIT,
aNRC_THINK_WAIT,
aNRC_THINK_NUM
};
enum {
aNRG_FORCE_TALK_CALL,
aNRG_FORCE_TALK_INTRODUCE,
aNRG_FORCE_TALK_EXPLAIN,
aNRG_FORCE_TALK_STOP_WADE,
aNRG_FORCE_TALK_BEFORE_OPEN_DOOR_TALK,
aNRG_FORCE_TALK_BEFORE_OPEN_DOOR2_TALK,
aNRG_FORCE_TALK_HOUSE_TAKEN,
aNRG_FORCE_TALK_HOUSE_VACANT,
aNRG_FORCE_TALK_NUM
};
enum {
aNRG_NORM_TALK_DECIDE_HOUSE,
aNRG_NORM_TALK_NUM
};
static void aNRG_actor_ct(ACTOR* actorx, GAME* game);
static void aNRG_actor_save(ACTOR* actorx, GAME* game);
static void aNRG_actor_dt(ACTOR* actorx, GAME* game);
static void aNRG_actor_init(ACTOR* actorx, GAME* game);
static void aNRG_actor_draw(ACTOR* actorx, GAME* game);
static void aNRG_actor_move(ACTOR* actorx, GAME* game);
// clang-format off
ACTOR_PROFILE Npc_Rcn_Guide_Profile = {
mAc_PROFILE_NPC_RCN_GUIDE,
ACTOR_PART_NPC,
ACTOR_STATE_CAN_MOVE_IN_DEMO_SCENES | ACTOR_STATE_NO_MOVE_WHILE_CULLED,
SP_NPC_RCN_GUIDE,
ACTOR_OBJ_BANK_KEEP,
sizeof(NPC_RCN_GUIDE_ACTOR),
&aNRG_actor_ct,
&aNRG_actor_dt,
&aNRG_actor_init,
mActor_NONE_PROC1,
&aNRG_actor_save,
};
// clang-format on
static void aNRG_force_talk_request(ACTOR* actorx, GAME* game);
static int aNRG_talk_init(ACTOR* actorx, GAME* game);
static int aNRG_talk_end_chk(ACTOR* actorx, GAME* game);
static void aNRG_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* game, int sched_idx);
static void aNRG_setup_think_proc(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play, int think_idx);
static void aNRG_actor_ct(ACTOR* actorx, GAME* game) {
// clang-format off
static aNPC_ct_data_c ct_data = {
&aNRG_actor_move,
&aNRG_actor_draw,
5,
&aNRG_force_talk_request,
&aNRG_talk_init,
&aNRG_talk_end_chk,
0,
};
// clang-format on
NPC_RCN_GUIDE_ACTOR* rcn_guide = (NPC_RCN_GUIDE_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
PLAYER_ACTOR* player;
s16 angle_y;
if (Common_Get(clip).npc_clip->birth_check_proc(actorx, &play->game) == TRUE) {
rcn_guide->npc_class.schedule.schedule_proc = &aNRG_schedule_proc;
Common_Get(clip).npc_clip->ct_proc(actorx, &play->game, &ct_data);
rcn_guide->npc_class.collision.priority = 2;
rcn_guide->melody_copy = rcn_guide->npc_class.talk_info.melody_inst;
/* Set shop acre */
mFI_BlockKind2BkNum(&rcn_guide->shop_bx, &rcn_guide->shop_bz, mRF_BLOCKKIND_SHOP);
rcn_guide->npc_class.draw.main_animation.keyframe.morph_counter = 0.0f;
rcn_guide->npc_class.actor_class.status_data.weight = 255;
player = GET_PLAYER_ACTOR(play);
if (player != NULL) {
angle_y = search_position_angleY(&rcn_guide->npc_class.actor_class.world.position,
&player->actor_class.world.position);
} else {
angle_y = 0;
}
rcn_guide->npc_class.actor_class.shape_info.rotation.y = angle_y;
rcn_guide->npc_class.actor_class.world.angle.y = angle_y;
}
}
static void aNRG_actor_save(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->save_proc(actorx, game);
}
static void aNRG_actor_dt(ACTOR* actorx, GAME* game) {
NPC_RCN_GUIDE_ACTOR* rcn_guide = (NPC_RCN_GUIDE_ACTOR*)actorx;
/* Stop playing the initial intro music when destruct due to entering a house */
if (rcn_guide->think_idx == aNRC_THINK_WAIT) {
mBGMPsComp_delete_ps_demo(BGM_INTRO_RCN_GUIDE, 0x168);
}
Common_Get(clip).npc_clip->dt_proc(actorx, game);
}
static void aNRG_actor_init(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->init_proc(actorx, game);
}
static void aNRG_actor_draw(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->draw_proc(actorx, game);
}
#include "../src/actor/ac_npc_rcn_guide_move.c_inc"
#include "../src/actor/ac_npc_rcn_guide_talk.c_inc"
#include "../src/actor/ac_npc_rcn_guide_schedule.c_inc"
+229
View File
@@ -0,0 +1,229 @@
#include "ac_npc_rcn_guide2.h"
#include "m_common_data.h"
#include "m_bgm.h"
#include "m_player_lib.h"
#include "m_font.h"
#include "m_msg.h"
#include "m_soncho.h"
#include "ac_intro_demo.h"
enum {
aNRG2_JOB1,
aNRG2_JOB2,
aNRG2_JOB3,
aNRG2_JOB4,
aNRG2_JOB5,
aNRG2_JOB6,
aNRG2_JOB7,
aNRG2_JOB8,
aNRG2_JOB9,
aNRG2_JOB10,
aNRG2_JOB11,
aNRG2_JOB_NUM
};
enum {
aNRG2_NORM_TALK_JOB1_START,
aNRG2_NORM_TALK_JOB2_START,
aNRG2_NORM_TALK_JOB3_START,
aNRG2_NORM_TALK_JOB4_START,
aNRG2_NORM_TALK_JOB5_START,
aNRG2_NORM_TALK_JOB5_2_START,
aNRG2_NORM_TALK_JOB6_START,
aNRG2_NORM_TALK_JOB7_START,
aNRG2_NORM_TALK_JOB10_START,
aNRG2_NORM_TALK_JOB11_START,
aNRG2_NORM_TALK_JOB1_REFUSE,
aNRG2_NORM_TALK_JOB2_REFUSE,
aNRG2_NORM_TALK_JOB3_REFUSE,
aNRG2_NORM_TALK_JOB4_REFUSE,
aNRG2_NORM_TALK_JOB5_REFUSE,
aNRG2_NORM_TALK_JOB5_2_REFUSE,
aNRG2_NORM_TALK_JOB6_REFUSE,
aNRG2_NORM_TALK_JOB7_REFUSE,
aNRG2_NORM_TALK_J1_CONT1,
aNRG2_NORM_TALK_J1_CONT2,
aNRG2_NORM_TALK_J1_CONT3,
aNRG2_NORM_TALK_J2_CONT1,
aNRG2_NORM_TALK_J3_CONT1,
aNRG2_NORM_TALK_J3_CONT2,
aNRG2_NORM_TALK_J4_CONT1,
aNRG2_NORM_TALK_J4_CONT2,
aNRG2_NORM_TALK_J5_CONT3,
aNRG2_NORM_TALK_J5_CONT1,
aNRG2_NORM_TALK_J5_CONT2,
aNRG2_NORM_TALK_J6_CONT1,
aNRG2_NORM_TALK_J6_CONT2,
aNRG2_NORM_TALK_J7_CONT1,
aNRG2_NORM_TALK_J10_CONT1,
aNRG2_NORM_TALK_J11_CONT1,
aNRG2_NORM_TALK_J1_END,
aNRG2_NORM_TALK_J2_END,
aNRG2_NORM_TALK_J3_END,
aNRG2_NORM_TALK_J4_END,
aNRG2_NORM_TALK_J5_END,
aNRG2_NORM_TALK_J6_END,
aNRG2_NORM_TALK_J7_END,
aNRG2_NORM_TALK_J10_END,
aNRG2_NORM_TALK_J11_END,
aNRG2_NORM_TALK_AGAIN,
aNRG2_NORM_TALK_NUM
};
enum {
aNRG2_FORCE_TALK_SAY_HELLO,
aNRG2_FORCE_TALK_SAY_HELLO2,
aNRG2_FORCE_TALK_SAY_HELLO_SP,
aNRG2_FORCE_TALK_CLOTH_CHK,
aNRG2_FORCE_TALK_UPSTAIR_CHK,
aNRG2_FORCE_TALK_NUM
};
enum {
aNRG2_THINK_SAY_HELLO,
aNRG2_THINK_SAY_HELLO2,
aNRG2_THINK_SAY_HELLO3,
aNRG2_THINK_SEND_AWAY,
aNRG2_THINK_TALK_START_WAIT,
aNRG2_THINK_JOB_START_WAIT,
aNRG2_THINK_ALL_JOB_END,
aNRG2_THINK_NUM
};
enum {
aNRG2_TALK_SAY_HELLO,
aNRG2_TALK_SAY_HELLO_SP,
aNRG2_TALK_SAY_HELLO_SP2,
aNRG2_TALK_CLOTH_CHK,
aNRG2_TALK_TALK_END_WAIT,
aNRG2_TALK_DEMO_START_WAIT,
aNRG2_TALK_DEMO_END_WAIT,
aNRG2_TALK_DEMO_END_WAIT2,
aNRG2_TALK_JOB_START,
aNRG2_TALK_JOB_END,
aNRG2_TALK_3RD_JOB_END,
aNRG2_TALK_DEMO2_START_WAIT,
aNRG2_TALK_DEMO2_START_WAIT2,
aNRG2_TALK_DEMO2_END,
aNRG2_TALK_GIVE_NEW_PAPER,
aNRG2_TALK_CHECK_MORE_PAPER,
aNRG2_TALK_DECIDE_NEW_TARGET,
aNRG2_TALK_DEMO3_START_WAIT,
aNRG2_TALK_DEMO3_START_WAIT2,
aNRG2_TALK_DEMO3_END_WAIT,
aNRG2_TALK_ALL_JOB_END,
aNRG2_TALK_NUM
};
typedef struct rcn_guide2_talk_info_s {
int msg_no;
aNRG2_TALK_PROC talk_proc;
} aNRG2_talk_info_c;
static void aNRG2_actor_ct(ACTOR* actorx, GAME* game);
static void aNRG2_actor_save(ACTOR* actorx, GAME* game);
static void aNRG2_actor_dt(ACTOR* actorx, GAME* game);
static void aNRG2_actor_init(ACTOR* actorx, GAME* game);
static void aNRG2_actor_draw(ACTOR* actorx, GAME* game);
static void aNRG2_actor_move(ACTOR* actorx, GAME* game);
// clang-format off
ACTOR_PROFILE Npc_Rcn_Guide2_Profile = {
mAc_PROFILE_NPC_RCN_GUIDE2,
ACTOR_PART_NPC,
ACTOR_STATE_NONE,
SP_NPC_RCN_GUIDE2,
ACTOR_OBJ_BANK_KEEP,
sizeof(NPC_RCN_GUIDE2_ACTOR),
&aNRG2_actor_ct,
&aNRG2_actor_dt,
&aNRG2_actor_init,
mActor_NONE_PROC1,
&aNRG2_actor_save,
};
// clang-format on
static void aNRG2_change_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2, int talk_proc_idx);
static void aNRG2_force_talk_request(ACTOR* actorx, GAME* game);
static int aNRG2_talk_init(ACTOR* actorx, GAME* game);
static int aNRG2_talk_end_chk(ACTOR* actorx, GAME* game);
static void aNRG2_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* game, int sched_idx);
static void aNRG2_setup_think_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2, GAME_PLAY* play, int think_idx);
static void aNRG2_actor_ct(ACTOR* actorx, GAME* game) {
// clang-format off
static aNPC_ct_data_c ct_data = {
&aNRG2_actor_move,
&aNRG2_actor_draw,
5,
&aNRG2_force_talk_request,
&aNRG2_talk_init,
&aNRG2_talk_end_chk,
1,
};
// clang-format on
NPC_RCN_GUIDE2_ACTOR* rcn_guide2 = (NPC_RCN_GUIDE2_ACTOR*)actorx;
if (Common_Get(clip).npc_clip->birth_check_proc(actorx, game) == TRUE) {
int shop_type = 0;
switch (actorx->npc_id) {
case SP_NPC_RCN_GUIDE2:
shop_type = 0;
break;
case SP_NPC_RCN_GUIDE2_1:
shop_type = 1;
break;
case SP_NPC_RCN_GUIDE2_2:
shop_type = 2;
break;
case SP_NPC_RCN_GUIDE2_3:
shop_type = 3;
break;
}
rcn_guide2->npc_class.draw.draw_type = shop_type;
rcn_guide2->npc_class.schedule.schedule_proc = &aNRG2_schedule_proc;
Common_Get(clip).npc_clip->ct_proc(actorx, game, &ct_data);
}
}
static void aNRG2_actor_save(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->save_proc(actorx, game);
}
static void aNRG2_actor_dt(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->dt_proc(actorx, game);
}
static void aNRG2_actor_init(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->init_proc(actorx, game);
}
static void aNRG2_actor_draw(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->draw_proc(actorx, game);
}
#include "../src/actor/ac_npc_rcn_guide2_move.c_inc"
#include "../src/actor/ac_npc_rcn_guide2_talk.c_inc"
#include "../src/actor/ac_npc_rcn_guide2_schedule.c_inc"
@@ -0,0 +1,30 @@
static void aNRG2_set_exit_info(ACTOR* actorx) {
GAME_PLAY* play = (GAME_PLAY*)gamePT;
if (goto_other_scene(play, Common_GetPointer(structure_exit_door_data), TRUE) != 1) {
mDemo_End(actorx);
} else {
mBGMPsComp_scene_mode(14);
mBGMPsComp_make_ps_wipe(0x195);
}
}
static void aNRG2_exit_check(ACTOR* actorx, GAME_PLAY* play) {
PLAYER_ACTOR* player = GET_PLAYER_ACTOR(play);
if (player != NULL && player->item_in_front == EXIT_DOOR1 && play->fb_wipe_mode == 0) {
mDemo_Request(mDemo_TYPE_EXITSCENE, actorx, &aNRG2_set_exit_info);
}
}
static void aNRG2_actor_move(ACTOR* actorx, GAME* game) {
NPC_RCN_GUIDE2_ACTOR* rcn_guide2 = (NPC_RCN_GUIDE2_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
if (rcn_guide2->npc_class.action.idx == aNPC_ACT_WAIT) {
rcn_guide2->npc_class.action.step = aNPC_ACTION_END_STEP;
}
Common_Get(clip).npc_clip->move_proc(actorx, game);
aNRG2_exit_check(actorx, play);
}
@@ -0,0 +1,374 @@
static int aNRG2_setup_j1_cont(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
int talk_idx = aNRG2_NORM_TALK_J1_CONT1;
if (mPr_GetPossessionItemIdxWithCond(Now_Private, ITM_CLOTH016, mPr_ITEM_COND_NORMAL) == -1) {
if (mPr_GetPossessionItemIdx(Now_Private, EMPTY_NO) == -1) {
talk_idx = aNRG2_NORM_TALK_J1_CONT3;
} else {
talk_idx = aNRG2_NORM_TALK_J1_CONT2;
}
}
return talk_idx;
}
static int aNRG2_setup_j2_cont(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
int talk_idx = aNRG2_NORM_TALK_J2_CONT1;
if (rcn_guide2->can_ask_again_flag == TRUE) {
talk_idx = aNRG2_NORM_TALK_AGAIN;
}
return talk_idx;
}
static int aNRG2_setup_j3_cont(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int talk_idx = aNRG2_NORM_TALK_J3_CONT1;
if (mQst_CheckRemoveTarget(errand_p) == TRUE) {
talk_idx = aNRG2_NORM_TALK_J3_CONT2;
} else if (rcn_guide2->can_ask_again_flag == TRUE) {
talk_idx = aNRG2_NORM_TALK_AGAIN;
}
return talk_idx;
}
static int aNRG2_setup_j4_cont(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int talk_idx = aNRG2_NORM_TALK_J4_CONT1;
if (rcn_guide2->can_ask_again_flag == TRUE) {
talk_idx = aNRG2_NORM_TALK_AGAIN;
} else if (mQst_CheckRemoveTarget(errand_p) == TRUE) {
talk_idx = aNRG2_NORM_TALK_J4_CONT2;
} else if (errand_p->base.progress == 3) {
talk_idx = aNRG2_NORM_TALK_J5_CONT3;
}
return talk_idx;
}
static int aNRG2_setup_j5_cont(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int talk_idx = aNRG2_NORM_TALK_J5_CONT1;
if (mQst_CheckRemoveTarget(errand_p) == TRUE) {
talk_idx = aNRG2_NORM_TALK_J5_CONT2;
}
return talk_idx;
}
static int aNRG2_setup_j6_cont(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int talk_idx = aNRG2_NORM_TALK_J6_CONT1;
if (mQst_CheckRemoveTarget(errand_p) == TRUE) {
talk_idx = aNRG2_NORM_TALK_J6_CONT2;
} else if (rcn_guide2->can_ask_again_flag == TRUE) {
talk_idx = aNRG2_NORM_TALK_AGAIN;
}
return talk_idx;
}
static int aNRG2_setup_j7_cont(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
int talk_idx = aNRG2_NORM_TALK_J7_CONT1;
if (rcn_guide2->can_ask_again_flag == TRUE) {
talk_idx = aNRG2_NORM_TALK_AGAIN;
}
return talk_idx;
}
static int aNRG2_setup_j10_cont(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
return aNRG2_NORM_TALK_J10_CONT1;
}
static int aNRG2_setup_j11_cont(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
return aNRG2_NORM_TALK_J11_CONT1;
}
typedef int (*aNRG2_SETUP_JOB_CONT_PROC)(NPC_RCN_GUIDE2_ACTOR*);
static void aNRG2_setup_job_cont(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
// clang-format off
static aNRG2_SETUP_JOB_CONT_PROC setup_job_cont_proc[] = {
&aNRG2_setup_j1_cont,
&aNRG2_setup_j2_cont,
&aNRG2_setup_j3_cont,
&aNRG2_setup_j4_cont,
&aNRG2_setup_j5_cont,
&aNRG2_setup_j6_cont,
&aNRG2_setup_j7_cont,
&aNRG2_setup_j4_cont,
&aNRG2_setup_j6_cont,
&aNRG2_setup_j10_cont,
&aNRG2_setup_j11_cont,
};
// clang-format on
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int idx = errand_p->base.quest_kind - mQst_ERRAND_FIRSTJOB_CHANGE_CLOTH;
rcn_guide2->talk_idx = (*setup_job_cont_proc[idx])(rcn_guide2);
}
static void aNRG2_talk_start_wait(NPC_RCN_GUIDE2_ACTOR* rcn_guide2, GAME_PLAY* play) {
// clang-format off
static int job_end_talk_idx[] = {
aNRG2_NORM_TALK_J1_END,
aNRG2_NORM_TALK_J2_END,
aNRG2_NORM_TALK_J3_END,
aNRG2_NORM_TALK_J4_END,
aNRG2_NORM_TALK_J5_END,
aNRG2_NORM_TALK_J6_END,
aNRG2_NORM_TALK_J7_END,
aNRG2_NORM_TALK_J4_END,
aNRG2_NORM_TALK_J6_END,
aNRG2_NORM_TALK_J10_END,
aNRG2_NORM_TALK_J11_END,
};
// clang-format on
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int idx = errand_p->base.quest_kind - mQst_ERRAND_FIRSTJOB_CHANGE_CLOTH;
if (mQst_CheckFirstJobFin(errand_p) == TRUE) {
rcn_guide2->talk_idx = job_end_talk_idx[idx];
rcn_guide2->can_ask_again_flag = FALSE;
} else {
aNRG2_setup_job_cont(rcn_guide2);
}
}
static void aNRG2_job_start_wait(NPC_RCN_GUIDE2_ACTOR* rcn_guide2, GAME_PLAY* play) {
// clang-format off
static int job_start_talk_idx[] = {
aNRG2_NORM_TALK_JOB1_START,
aNRG2_NORM_TALK_JOB2_START,
aNRG2_NORM_TALK_JOB3_START,
aNRG2_NORM_TALK_JOB4_START,
aNRG2_NORM_TALK_JOB5_START,
aNRG2_NORM_TALK_JOB6_START,
aNRG2_NORM_TALK_JOB7_START,
aNRG2_NORM_TALK_JOB4_START,
aNRG2_NORM_TALK_JOB6_START,
aNRG2_NORM_TALK_JOB10_START,
aNRG2_NORM_TALK_JOB11_START,
};
// clang-format on
// clang-format off
static int job_start_refuse_talk_idx[] = {
aNRG2_NORM_TALK_JOB1_REFUSE,
aNRG2_NORM_TALK_JOB2_REFUSE,
aNRG2_NORM_TALK_JOB3_REFUSE,
aNRG2_NORM_TALK_JOB4_REFUSE,
aNRG2_NORM_TALK_JOB5_REFUSE,
aNRG2_NORM_TALK_JOB6_REFUSE,
aNRG2_NORM_TALK_JOB7_REFUSE,
aNRG2_NORM_TALK_JOB4_REFUSE,
aNRG2_NORM_TALK_JOB6_REFUSE,
-1,
-1,
};
// clang-format on
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int idx = errand_p->base.quest_kind - mQst_ERRAND_FIRSTJOB_CHANGE_CLOTH;
if (aNRG2_check_job_start() == TRUE) {
rcn_guide2->talk_idx = job_start_talk_idx[idx];
} else {
rcn_guide2->talk_idx = job_start_refuse_talk_idx[idx];
}
}
static void aNRG2_all_job_end(NPC_RCN_GUIDE2_ACTOR* rcn_guide2, GAME_PLAY* play) {
if (play->fb_wipe_mode == 0) {
rcn_guide2->counter++;
if (rcn_guide2->counter > 60) {
aNRG2_setup_think_proc(rcn_guide2, play, aNRG2_THINK_SEND_AWAY);
}
}
}
static void aNRG2_think_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
NPC_RCN_GUIDE2_ACTOR* rcn_guide2 = (NPC_RCN_GUIDE2_ACTOR*)nactorx;
if (nactorx->action.step == aNPC_ACTION_END_STEP) {
(*rcn_guide2->think_proc)(rcn_guide2, play);
}
}
static void aNRG2_think_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
NPC_RCN_GUIDE2_ACTOR* rcn_guide2 = (NPC_RCN_GUIDE2_ACTOR*)nactorx;
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int think_idx;
rcn_guide2->npc_class.condition_info.hide_request = FALSE;
rcn_guide2->npc_class.actor_class.status_data.weight = 255;
rcn_guide2->npc_class.actor_class.shape_info.rotation.y = rcn_guide2->npc_class.actor_class.player_angle_y;
rcn_guide2->npc_class.actor_class.world.angle.y = rcn_guide2->npc_class.actor_class.player_angle_y;
if (Common_Get(quest).work == 0) {
Common_Get(quest).work = 1;
rcn_guide2->daily_speak_flag = TRUE;
if (errand_p->base.quest_kind == mQst_ERRAND_FIRSTJOB_START) {
if (Now_Private->cloth.item == ITM_CLOTH016) {
aNRG2_setup_job(aNRG2_JOB2);
think_idx = aNRG2_THINK_SAY_HELLO3;
} else {
aNRG2_setup_job(aNRG2_JOB1);
think_idx = aNRG2_THINK_SAY_HELLO;
}
} else {
think_idx = aNRG2_THINK_SAY_HELLO2;
}
} else if (errand_p->base.progress == 1) {
think_idx = aNRG2_THINK_JOB_START_WAIT;
} else {
think_idx = aNRG2_THINK_TALK_START_WAIT;
}
if (Save_Get(scene_no) == SCENE_DEPART) {
/* Replace the upstairs warps with reserve items */
mFI_UtNumtoFGSet_common(RSV_POLICE_ITEM_0, 7, 1, FALSE);
mFI_UtNumtoFGSet_common(RSV_POLICE_ITEM_0, 8, 1, FALSE);
}
aNRG2_setup_think_proc(rcn_guide2, play, think_idx);
}
static void aNRG2_send_away_init(NPC_RCN_GUIDE2_ACTOR* rcn_guide2, GAME_PLAY* play) {
goto_other_scene(play, Common_GetPointer(structure_exit_door_data), 1);
mBGMPsComp_scene_mode(14);
}
static void aNRG2_talk_start_wait_init(NPC_RCN_GUIDE2_ACTOR* rcn_guide2, GAME_PLAY* play) {
aNRG2_talk_start_wait(rcn_guide2, play);
}
static void aNRG2_job_start_wait_init(NPC_RCN_GUIDE2_ACTOR* rcn_guide2, GAME_PLAY* play) {
aNRG2_job_start_wait(rcn_guide2, play);
}
static void aNRG2_all_job_end_init(NPC_RCN_GUIDE2_ACTOR* rcn_guide2, GAME_PLAY* play) {
INTRO_DEMO_ACTOR* intro_demo;
mPlib_request_main_demo_wait_type1(&play->game, 0, NULL);
intro_demo =
(INTRO_DEMO_ACTOR*)Actor_info_name_search(&play->actor_info, mAc_PROFILE_INTRO_DEMO, ACTOR_PART_CONTROL);
intro_demo->_1A8 = TRUE;
}
typedef void (*aNRG2_THINK_INIT_PROC)(NPC_RCN_GUIDE2_ACTOR*, GAME_PLAY*);
typedef struct rcn_guide2_think_data_s {
aNRG2_THINK_PROC think_proc;
aNRG2_THINK_INIT_PROC think_init_proc;
aNPC_TALK_REQUEST_PROC talk_request_proc;
u8 talk_idx;
u8 next_think_idx;
} aNRG2_think_data_c;
static void aNRG2_setup_think_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2, GAME_PLAY* play, int think_idx) {
// clang-format off
static aNRG2_think_data_c dt_tbl[] = {
{
(aNRG2_THINK_PROC)&none_proc1,
(aNRG2_THINK_INIT_PROC)&none_proc1,
&aNRG2_force_talk_request,
aNRG2_FORCE_TALK_SAY_HELLO,
aNRG2_THINK_SEND_AWAY,
},
{
(aNRG2_THINK_PROC)&none_proc1,
(aNRG2_THINK_INIT_PROC)&none_proc1,
&aNRG2_force_talk_request,
aNRG2_FORCE_TALK_SAY_HELLO2,
aNRG2_THINK_SEND_AWAY,
},
{
(aNRG2_THINK_PROC)&none_proc1,
(aNRG2_THINK_INIT_PROC)&none_proc1,
&aNRG2_force_talk_request,
aNRG2_FORCE_TALK_SAY_HELLO_SP,
aNRG2_THINK_SEND_AWAY,
},
{
(aNRG2_THINK_PROC)&none_proc1,
&aNRG2_send_away_init,
(aNPC_TALK_REQUEST_PROC)&none_proc1,
0,
aNRG2_THINK_SEND_AWAY,
},
{
&aNRG2_talk_start_wait,
&aNRG2_talk_start_wait_init,
&aNRG2_norm_talk_request,
aNRG2_NORM_TALK_JOB1_START,
aNRG2_THINK_TALK_START_WAIT,
},
{
&aNRG2_job_start_wait,
&aNRG2_job_start_wait_init,
&aNRG2_norm_talk_request,
aNRG2_NORM_TALK_JOB1_START,
aNRG2_THINK_JOB_START_WAIT,
},
{
&aNRG2_all_job_end,
&aNRG2_all_job_end_init,
(aNPC_TALK_REQUEST_PROC)&none_proc1,
0,
aNRG2_THINK_ALL_JOB_END,
},
};
// clang-format on
aNRG2_think_data_c* data = &dt_tbl[think_idx];
static u16 arg_data[6] = { 0, 0, 0, 0, 0, 0 };
rcn_guide2->think_idx = think_idx;
rcn_guide2->think_proc = data->think_proc;
rcn_guide2->npc_class.talk_info.talk_request_proc = data->talk_request_proc;
rcn_guide2->talk_idx = data->talk_idx;
rcn_guide2->next_think_idx = data->next_think_idx;
rcn_guide2->npc_class.request.act_priority = 1;
rcn_guide2->npc_class.request.act_idx = aNPC_ACT_WAIT;
rcn_guide2->npc_class.request.act_type = aNPC_ACT_TYPE_DEFAULT;
mem_copy((u8*)rcn_guide2->npc_class.request.act_args, (u8*)arg_data, sizeof(arg_data));
(*data->think_init_proc)(rcn_guide2, play);
}
static void aNRG2_think_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) {
static aNPC_SUB_PROC think_proc[] = { &aNRG2_think_init_proc, &aNRG2_think_main_proc };
(*think_proc[proc_type])(nactorx, play);
}
static void aNRG2_schedule_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
nactorx->think.think_proc = &aNRG2_think_proc;
Common_Get(clip).npc_clip->think_proc(nactorx, play, aNPC_THINK_IN_BLOCK, 0);
}
static void aNRG2_schedule_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
int res = Common_Get(clip).npc_clip->think_proc(nactorx, play, -1, 1);
if (res == 0) {
Common_Get(clip).npc_clip->think_proc(nactorx, play, -1, 2);
}
}
static void aNRG2_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) {
static aNPC_SUB_PROC sche_proc[] = { &aNRG2_schedule_init_proc, &aNRG2_schedule_main_proc };
(*sche_proc[proc_type])(nactorx, play);
}
+912
View File
@@ -0,0 +1,912 @@
static void aNRG2_set_str_j3(void) {
static u8 choume_str[] = { 'Q', 'A', 'B', 'C', 'D', 'E', 'F' };
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
mQst_errand_c* errand_p = mQst_GetFirstJobData();
AnmPersonalID_c* to_id_p = &errand_p->recipient;
int idx = mNpc_SearchAnimalinfo(Save_Get(animals), to_id_p->npc_id, ANIMAL_NUM_MAX);
u8 str[ANIMAL_NAME_LEN];
if (idx != -1) {
/* Set msg string 3 & 4 to acre Z & X respectively */
Anmhome_c* home_p = &Save_Get(animals[idx]).home_info;
mMsg_Set_free_str(msg_p, mMsg_FREE_STR3, &choume_str[home_p->block_z], 1);
mFont_UnintToString(str, sizeof(str), home_p->block_x, sizeof(str), TRUE, FALSE, TRUE);
mMsg_Set_free_str(msg_p, mMsg_FREE_STR4, str, sizeof(str));
}
mNpc_GetNpcWorldNameAnm(str, to_id_p);
mMsg_Set_free_str_cl(msg_p, mMsg_FREE_STR5, str, sizeof(str), 1);
}
static void aNRG2_set_str_j4(void) {
int bx;
int bz;
u8 str[1];
/* Set recipient home acre */
aNRG2_set_str_j3();
/* Set post office acre string */
mFI_BlockKind2BkNum(&bx, &bz, mRF_BLOCKKIND_POSTOFFICE);
mFont_UnintToString(str, sizeof(str), bx, sizeof(str), TRUE, FALSE, TRUE);
/* We only care about the X acre since the post office is always in the A row */
mMsg_SET_FREE_STR(mMsg_FREE_STR6, str, sizeof(str));
}
typedef void (*aNRG2_SET_STR_PROC)(void);
static void aNRG2_set_str_proc(void) {
static aNRG2_SET_STR_PROC process[] = {
(aNRG2_SET_STR_PROC)&none_proc1,
(aNRG2_SET_STR_PROC)&none_proc1,
&aNRG2_set_str_j3,
&aNRG2_set_str_j4,
&aNRG2_set_str_j3,
&aNRG2_set_str_j3,
(aNRG2_SET_STR_PROC)&none_proc1,
&aNRG2_set_str_j4,
&aNRG2_set_str_j3,
(aNRG2_SET_STR_PROC)&none_proc1,
(aNRG2_SET_STR_PROC)&none_proc1,
};
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int idx = errand_p->base.quest_kind - mQst_ERRAND_FIRSTJOB_CHANGE_CLOTH;
/* Set the current job strings, index is job quest idx relative to first job */
(*process[idx])();
}
static void aNRG2_set_possession(void) {
// clang-format off
static mActor_name_t set_itemNo[] = {
ITM_CLOTH016,
ITM_WHITE_PANSY_BAG,
EMPTY_NO,
ITM_PAPER55,
EMPTY_NO,
ITM_AXE,
EMPTY_NO,
ITM_PAPER55,
ITM_AXE,
EMPTY_NO,
EMPTY_NO,
};
// clang-format on
mQst_errand_c* errand_p = mQst_GetFirstJobData();
u32 job_kind = errand_p->base.quest_kind - mQst_ERRAND_FIRSTJOB_CHANGE_CLOTH;
if (job_kind == aNRG2_JOB2) {
int i;
/* Give player 7 random flower bags */
for (i = 0; i < 7; i++) {
mActor_name_t item = ITM_WHITE_PANSY_BAG + RANDOM(9);
mPr_SetFreePossessionItem(Now_Private, item, mPr_ITEM_COND_NORMAL);
}
/* Give player 3 saplings */
for (i = 0; i < 3; i++) {
mPr_SetFreePossessionItem(Now_Private, ITM_SAPLING, mPr_ITEM_COND_NORMAL);
}
} else {
switch (job_kind) {
case aNRG2_JOB3:
case aNRG2_JOB5:
/* Set the random errand item with quest condition */
mPr_SetFreePossessionItem(Now_Private, errand_p->item, mPr_ITEM_COND_QUEST);
break;
case aNRG2_JOB1:
case aNRG2_JOB4:
case aNRG2_JOB7:
case aNRG2_JOB8:
/* Set the static job item with normal condition */
mPr_SetFreePossessionItem(Now_Private, set_itemNo[job_kind], mPr_ITEM_COND_NORMAL);
break;
case aNRG2_JOB2:
case aNRG2_JOB6:
case aNRG2_JOB9:
default:
/* Set the static job item with quest condition */
mPr_SetFreePossessionItem(Now_Private, set_itemNo[job_kind], mPr_ITEM_COND_QUEST);
break;
case aNRG2_JOB10:
case aNRG2_JOB11:
break;
}
}
}
static int aNRG2_check_job_start(void) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int res = FALSE;
u32 free_slots = mPr_GetPossessionItemSum(Now_Private, EMPTY_NO);
switch (errand_p->base.quest_kind) {
case mQst_ERRAND_FIRSTJOB_PLANT_FLOWER:
/* Need at least 10 inventory slots free for the planting chore */
if (free_slots >= 10) {
res = TRUE;
}
break;
case mQst_ERRAND_FIRSTJOB_POST_NOTICE:
case mQst_ERRAND_FIRSTJOB_INTRODUCTIONS:
case mQst_ERRAND_FIRSTJOB_OPEN:
/* These chores have no items and thus can always be started */
res = TRUE;
break;
default:
/* Default requires at least one free inventory slot */
if (free_slots > 0) {
res = TRUE;
}
break;
}
return res;
}
/* Is this a typo of setup? */
static void aNRG2_stepup_j1(u32 kind, NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
/* Job 1: change into 'work clothes' */
mQst_SetFirstJobChangeCloth(errand_p, ITM_CLOTH016);
}
static void aNRG2_stepup_j2(u32 kind, NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
/* Job 2: plant flower seeds & tree saplings */
mQst_SetFirstJobSeed(errand_p);
}
static void aNRG2_stepup_j3(u32 kind, NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
/* List of 'no good' furniture, seemingly only ones you can walk on? */
static mActor_name_t ng_list[] = { FTR_MANHOLE_COVER, FTR_BATH_MAT };
mQst_errand_c* errand_p;
AnmPersonalID_c* anm_pid_p;
mActor_name_t ftr;
u32 free_idx;
/* Get first job quest data */
errand_p = mQst_GetFirstJobData();
/* Get first free inventory slot index */
free_idx = mPr_GetPossessionItemIdx(Now_Private, EMPTY_NO);
/* Get an unused target villager for delivery target */
anm_pid_p = mNpc_GetOtherAnimalPersonalID(errand_p->info.first_job.used_ids, errand_p->info.first_job.used_num);
/* Roll random ABC list furniture to be delivered */
mSP_SelectRandomItem_New(NULL, &ftr, 1, ng_list, ARRAY_COUNT(ng_list), mSP_KIND_FURNITURE, mSP_LISTTYPE_ABC, FALSE);
/* Job 3: deliver furniture */
mQst_SetFirstJobFurniture(errand_p, anm_pid_p, ftr, free_idx);
}
static void aNRG2_stepup_j4(u32 kind, NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mQst_errand_c* errand_p;
AnmPersonalID_c* anm_pid_p;
// Get first job quest data
errand_p = mQst_GetFirstJobData();
// Get an unused target villager for letter recipient
anm_pid_p = mNpc_GetOtherAnimalPersonalID(errand_p->info.first_job.used_ids, errand_p->info.first_job.used_num);
// Force a memory with the animal in the event the player hasn't spoken to them yet
// This could happen if an animal moves in before the chore is started,
// but after the introductions sequence is finished.
// This prevents the case where the recipient would not be listed
// in the recipient menu despite being assigned by Nook.
mNpc_SetAnimalPersonalID2Memory(anm_pid_p);
// Job 4: send letter
if (kind == aNRG2_JOB4) {
mQst_SetFirstJobLetter(errand_p, anm_pid_p);
} else {
mQst_SetFirstJobLetter2(errand_p, anm_pid_p);
}
// Allow Nook to remind the player about this chore
rcn_guide2->can_ask_again_flag = TRUE;
}
static void aNRG2_stepup_j5(u32 kind, NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mQst_errand_c* errand_p;
AnmPersonalID_c* anm_pid_p;
mActor_name_t ftr;
u32 free_idx;
/* Get first job quest data */
errand_p = mQst_GetFirstJobData();
/* Get first free inventory slot index */
free_idx = mPr_GetPossessionItemIdx(Now_Private, EMPTY_NO);
/* Get an unused target villager for delivery target */
anm_pid_p = mNpc_GetOtherAnimalPersonalID(errand_p->info.first_job.used_ids, errand_p->info.first_job.used_num);
/* Roll random ABC list carpet to be delivered */
mSP_SelectRandomItem_New(NULL, &ftr, 1, NULL, 0, mSP_KIND_CARPET, mSP_LISTTYPE_ABC, FALSE);
/* Job 5: deliver carpet */
mQst_SetFirstJobCarpet(errand_p, anm_pid_p, ftr, free_idx);
}
static void aNRG2_stepup_j6(u32 kind, NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mQst_errand_c* errand_p;
u32 free_idx;
// Get first job quest data
errand_p = mQst_GetFirstJobData();
// Get the first free inventory slot
free_idx = mPr_GetPossessionItemIdx(Now_Private, EMPTY_NO);
// Job 5: deliver axe
if (kind == aNRG2_JOB6) {
mQst_SetFirstJobAxe(errand_p, &errand_p->info.first_job.used_ids[1], ITM_AXE, free_idx);
} else {
mQst_SetFirstJobAxe2(errand_p, &errand_p->info.first_job.used_ids[1], ITM_AXE, free_idx);
}
}
static void aNRG2_stepup_j7(u32 kind, NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
/* Job 7: post on notice board */
mQst_SetFirstJobNotice(errand_p);
}
static void aNRG2_stepup_j10(u32 kind, NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
/* Job 10: introductions */
mQst_SetFirstJobHello(errand_p);
}
static void aNRG2_stepup_j11(u32 kind, NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
/* Job 11: open quest */
mQst_SetFirstJobOpenQuest(errand_p);
}
typedef void (*aNRG2_STEPUP_PROC)(u32, NPC_RCN_GUIDE2_ACTOR*);
static void aNRG2_stepup_job(NPC_RCN_GUIDE2_ACTOR* rcn_guide2, u32 job_kind) {
// clang-format off
static aNRG2_STEPUP_PROC stepup_job_proc[] = {
&aNRG2_stepup_j1,
&aNRG2_stepup_j2,
&aNRG2_stepup_j3,
&aNRG2_stepup_j4,
&aNRG2_stepup_j5,
&aNRG2_stepup_j6,
&aNRG2_stepup_j7,
&aNRG2_stepup_j4,
&aNRG2_stepup_j6,
&aNRG2_stepup_j10,
&aNRG2_stepup_j11,
};
// clang-format on
mQst_errand_c* errand_p = mQst_GetFirstJobData();
if (errand_p->base.progress == 1) {
(*stepup_job_proc[job_kind])(job_kind, rcn_guide2);
aNRG2_set_str_proc();
}
}
static void aNRG2_setup_job(int job_kind) {
// clang-format off
static u32 kind[] = {
mQst_ERRAND_FIRSTJOB_CHANGE_CLOTH,
mQst_ERRAND_FIRSTJOB_PLANT_FLOWER,
mQst_ERRAND_FIRSTJOB_DELIVER_FTR,
mQst_ERRAND_FIRSTJOB_SEND_LETTER,
mQst_ERRAND_FIRSTJOB_DELIVER_CARPET,
mQst_ERRAND_FIRSTJOB_DELIVER_AXE,
mQst_ERRAND_FIRSTJOB_POST_NOTICE,
mQst_ERRAND_FIRSTJOB_SEND_LETTER2,
mQst_ERRAND_FIRSTJOB_DELIVER_AXE2,
mQst_ERRAND_FIRSTJOB_INTRODUCTIONS,
mQst_ERRAND_FIRSTJOB_OPEN,
};
// clang-format on
mQst_errand_c* errand_p = mQst_GetFirstJobData();
errand_p->base.quest_kind = kind[job_kind];
errand_p->base.progress = 1;
}
static void aNRG2_say_hello_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
// clang-format off
static int job_start_msg_no[] = {
0x07F1,
0x07F6,
0x07FB,
0x0802,
0x080C,
0x0813,
0x0818,
0x0802,
0x0813,
0x0821,
0x0827,
};
// clang-format on
// clang-format off
static int job_start_refuse_msg_no[] = {
0x07F0,
0x07F5,
0x07FA,
0x07FA,
0x07FA,
0x07FA,
0x0818,
0x07FA,
0x07FA,
-1,
-1,
};
// clang-format on
static int next_talk_idx[] = { aNRG2_TALK_DEMO_START_WAIT, aNRG2_TALK_TALK_END_WAIT };
mMsg_Window_c* msg_p;
mQst_errand_c* errand_p;
int msg_no;
int talk_idx;
int job_kind;
msg_p = mMsg_Get_base_window_p();
errand_p = mQst_GetFirstJobData();
if (errand_p->base.progress == 1) {
job_kind = errand_p->base.quest_kind - mQst_ERRAND_FIRSTJOB_CHANGE_CLOTH;
if (aNRG2_check_job_start() == TRUE) {
/* The next job can be started */
// Initial setup
aNRG2_stepup_job(rcn_guide2, job_kind);
// Set quest items if necessary
aNRG2_set_possession();
// Setup params
msg_no = job_start_msg_no[job_kind];
rcn_guide2->next_think_idx = aNRG2_THINK_TALK_START_WAIT;
talk_idx = 0;
} else {
/* The next job can't be started */
msg_no = job_start_refuse_msg_no[job_kind];
rcn_guide2->next_think_idx = aNRG2_THINK_JOB_START_WAIT;
talk_idx = 1;
}
mMsg_Set_continue_msg_num(msg_p, msg_no);
aNRG2_change_talk_proc(rcn_guide2, next_talk_idx[talk_idx]);
} else {
/* We're still in the middle of a job? */
rcn_guide2->next_think_idx = aNRG2_THINK_TALK_START_WAIT;
mMsg_Set_CancelNormalContinue(msg_p);
aNRG2_change_talk_proc(rcn_guide2, aNRG2_TALK_TALK_END_WAIT);
}
}
static void aNRG2_say_hello_sp_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
/* Special message on first meeting at shop if player is already wearing uniform */
mMsg_SET_CONTINUE_MSG_NUM(0x0837);
aNRG2_change_talk_proc(rcn_guide2, aNRG2_TALK_SAY_HELLO_SP2);
}
static void aNRG2_say_hello_sp2_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
if (mMsg_GET_MSG_NUM() == 0x0837) {
aNRG2_say_hello_talk_proc(rcn_guide2);
}
}
static void aNRG2_cloth_chk_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
if (errand_p->base.progress == 1) {
rcn_guide2->next_think_idx = aNRG2_THINK_JOB_START_WAIT;
} else {
rcn_guide2->next_think_idx = aNRG2_THINK_TALK_START_WAIT;
}
aNRG2_change_talk_proc(rcn_guide2, aNRG2_TALK_TALK_END_WAIT);
}
static void aNRG2_demo_start_wait_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
/* List of display items for each job */
static mActor_name_t itemNo[] = {
ITM_CLOTH016, /* work uniform */
ITM_WHITE_PANSY_BAG, /* flower bag */
FTR_FAN, /* furniture */
ITM_PAPER55, /* simple paper */
ITM_CARPET00, /* carpet */
ITM_AXE, /* axe */
EMPTY_NO, /* no item */
ITM_PAPER55, /* simple paper */
ITM_AXE, /* axe */
EMPTY_NO, /* no item */
EMPTY_NO, /* no item */
};
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 1);
if (order == 4) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
u32 kind = errand_p->base.quest_kind - mQst_ERRAND_FIRSTJOB_CHANGE_CLOTH;
/* Set params for hand over item */
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 0, itemNo[kind]);
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 1, 7);
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 2, 0);
/* Don't let the player continue dialog */
mMsg_SET_LOCKCONTINUE();
aNRG2_change_talk_proc(rcn_guide2, aNRG2_TALK_DEMO_END_WAIT);
}
}
static void aNRG2_demo_end_wait_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
/* Wait for the hand over process item to start */
if (rcn_guide2->npc_class.action.idx == 10 && Common_Get(clip).handOverItem_clip->master_actor != NULL) {
aNRG2_change_talk_proc(rcn_guide2, aNRG2_TALK_DEMO_END_WAIT2);
}
}
static void aNRG2_demo_end_wait2_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
/* Wait for the hand over item process to finish */
if (Common_Get(clip).handOverItem_clip->master_actor == NULL) {
/* Allow player to continue dialog */
mMsg_UNSET_LOCKCONTINUE();
aNRG2_change_talk_proc(rcn_guide2, aNRG2_TALK_TALK_END_WAIT);
}
}
static void aNRG2_job_start_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int talk_proc_idx;
/* Setup job quest info */
aNRG2_stepup_job(rcn_guide2, errand_p->base.quest_kind - mQst_ERRAND_FIRSTJOB_CHANGE_CLOTH);
/* Give the player the necessary item(s) for the job */
aNRG2_set_possession();
if (errand_p->base.quest_kind == mQst_ERRAND_FIRSTJOB_INTRODUCTIONS ||
errand_p->base.quest_kind == mQst_ERRAND_FIRSTJOB_OPEN) {
talk_proc_idx = aNRG2_TALK_TALK_END_WAIT;
} else {
talk_proc_idx = aNRG2_TALK_DEMO_START_WAIT;
}
aNRG2_change_talk_proc(rcn_guide2, talk_proc_idx);
rcn_guide2->next_think_idx = aNRG2_THINK_TALK_START_WAIT;
}
static void aNRG2_job_end_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
static int next_job_no[] = {
aNRG2_JOB2, aNRG2_JOB3, aNRG2_JOB4, aNRG2_JOB11, aNRG2_JOB6, aNRG2_JOB7,
aNRG2_JOB7, aNRG2_JOB9, aNRG2_JOB7, aNRG2_JOB3, aNRG2_JOB5,
};
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int next_job;
/* If the finished quest was the planting flowers & saplings job & the player hasn't spoken to all villagers &
* Tortimer, then set the job to introductions.
*/
if (errand_p->base.quest_kind == mQst_ERRAND_FIRSTJOB_PLANT_FLOWER &&
(mNpc_CheckFriendAllAnimal(&Now_Private->player_ID) == FALSE || mSC_check_ArbeitPlayer() == FALSE)) {
next_job = aNRG2_JOB10;
} else {
next_job = next_job_no[errand_p->base.quest_kind - mQst_ERRAND_FIRSTJOB_CHANGE_CLOTH];
}
aNRG2_setup_job(next_job);
aNRG2_change_talk_proc(rcn_guide2, aNRG2_TALK_SAY_HELLO);
}
static void aNRG2_3rd_job_end_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
u16 order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
/* Hand over the map */
if (order != 0) {
aNRG2_job_end_talk_proc(rcn_guide2);
/* Set params for hand over item */
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 1, 2);
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 0, ITM_TOWN_MAP);
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 1, 7);
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 2, 0);
/* Enable map flag */
Common_Set(map_flag, TRUE);
/* Clear demo order */
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
}
static void aNRG2_demo2_start_wait_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
u16 order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
/* Take quest item back from player */
if (order != 0) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int idx = mPr_GetPossessionItemIdxWithCond(Now_Private, errand_p->item, mPr_ITEM_COND_QUEST);
// This is bad, if you somehow don't have the quest item, the first item in your inventory will be deleted
if (idx == -1) {
idx = 0;
}
/* Clear item */
mPr_SetPossessionItem(Now_Private, idx, 0, mPr_ITEM_COND_NORMAL);
/* Clear demo order */
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
/* Prevent player from continuing dialogue */
mMsg_SET_LOCKCONTINUE();
/* Tell the player to play hand over animation */
mPlib_request_main_give_type1(gamePT, errand_p->item, 7, FALSE, FALSE);
aNRG2_setup_job(errand_p->base.quest_kind - mQst_ERRAND_FIRSTJOB_CHANGE_CLOTH);
aNRG2_change_talk_proc(rcn_guide2, aNRG2_TALK_DEMO2_START_WAIT2);
}
}
static void aNRG2_demo2_start_wait2_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
/* Wait for hand over item request mode */
if (Common_Get(clip).handOverItem_clip->request_mode == aHOI_REQUEST_TRANS_WAIT) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 1, 3);
aNRG2_change_talk_proc(rcn_guide2, aNRG2_TALK_DEMO2_END);
}
}
static void aNRG2_demo2_end_wait_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
/* Wait for hand over item to finish */
if (Common_Get(clip).handOverItem_clip->master_actor == NULL) {
/* Allow player to continue the dialogue now */
mMsg_UNSET_LOCKCONTINUE();
aNRG2_job_start_talk_proc(rcn_guide2);
}
}
static void aNRG2_give_new_paper_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
if (aNRG2_check_job_start() == TRUE) {
/* Give another piece of stationery to the player */
mMsg_Set_continue_msg_num(msg_p, 0x0805); // 'Here! Here's another piece of paper.'
aNRG2_job_start_talk_proc(rcn_guide2);
rcn_guide2->can_ask_again_flag = TRUE;
} else {
/* Player has full pockets so tell them */
mMsg_Set_continue_msg_num(msg_p, 0x07FA); // '...What have we here?'
aNRG2_change_talk_proc(rcn_guide2, aNRG2_TALK_TALK_END_WAIT);
rcn_guide2->can_ask_again_flag = FALSE;
}
}
static void aNRG2_check_more_paper_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
u16 order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
mQst_errand_c* errand_p;
if (order != 0) {
/* Clear the demo order */
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0:
/* Player asked for more paper, so give them some if they have inv space */
errand_p = mQst_GetFirstJobData();
aNRG2_give_new_paper_talk_proc(rcn_guide2);
errand_p->base.progress = 2;
break;
case mChoice_CHOICE1:
/* Player said they don't need more paper */
aNRG2_change_talk_proc(rcn_guide2, aNRG2_TALK_TALK_END_WAIT);
rcn_guide2->can_ask_again_flag = FALSE;
break;
}
}
}
static void aNRG2_decide_new_target_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
u16 order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
mQst_errand_c* errand_p;
if (order != 0) {
errand_p = mQst_GetFirstJobData();
/* Clear the demo order */
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
aNRG2_setup_job(errand_p->base.quest_kind - mQst_ERRAND_FIRSTJOB_CHANGE_CLOTH);
aNRG2_stepup_job(rcn_guide2, errand_p->base.quest_kind - mQst_ERRAND_FIRSTJOB_CHANGE_CLOTH);
aNRG2_change_talk_proc(rcn_guide2, aNRG2_TALK_CHECK_MORE_PAPER);
}
}
static void aNRG2_demo3_start_wait_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
u16 order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
mQst_errand_c* errand_p;
int idx;
if (order != 0) {
errand_p = mQst_GetFirstJobData();
idx = mPr_GetPossessionItemIdxWithCond(Now_Private, errand_p->item, mPr_ITEM_COND_QUEST);
if (idx == -1) {
/* If the job's tool item can't be found then try the player's equipped item */
if (Now_Private->equipment == errand_p->item) {
Now_Private->equipment = EMPTY_NO;
}
} else {
mPr_SetPossessionItem(Now_Private, idx, EMPTY_NO, mPr_ITEM_COND_NORMAL);
}
/* Clear the demo order */
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
mMsg_SET_LOCKCONTINUE();
mPlib_request_main_give_type1(gamePT, errand_p->item, 7, FALSE, FALSE);
aNRG2_setup_job(aNRG2_JOB8);
aNRG2_change_talk_proc(rcn_guide2, aNRG2_TALK_DEMO3_START_WAIT2);
}
}
static void aNRG2_all_job_end_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2) {
rcn_guide2->next_think_idx = aNRG2_THINK_ALL_JOB_END;
aNRG2_change_talk_proc(rcn_guide2, aNRG2_TALK_TALK_END_WAIT);
}
static void aNRG2_change_talk_proc(NPC_RCN_GUIDE2_ACTOR* rcn_guide2, int talk_proc_idx) {
// clang-format off
static aNRG2_TALK_PROC proc[] = {
&aNRG2_say_hello_talk_proc,
&aNRG2_say_hello_sp_talk_proc,
&aNRG2_say_hello_sp2_talk_proc,
&aNRG2_cloth_chk_talk_proc,
(aNRG2_TALK_PROC)&none_proc1,
&aNRG2_demo_start_wait_talk_proc,
&aNRG2_demo_end_wait_talk_proc,
&aNRG2_demo_end_wait2_talk_proc,
&aNRG2_job_start_talk_proc,
&aNRG2_job_end_talk_proc,
&aNRG2_3rd_job_end_talk_proc,
&aNRG2_demo2_start_wait_talk_proc,
&aNRG2_demo2_start_wait2_talk_proc,
&aNRG2_demo2_end_wait_talk_proc,
&aNRG2_give_new_paper_talk_proc,
&aNRG2_check_more_paper_talk_proc,
&aNRG2_decide_new_target_talk_proc,
&aNRG2_demo3_start_wait_talk_proc,
&aNRG2_demo2_start_wait2_talk_proc,
&aNRG2_demo2_end_wait_talk_proc,
&aNRG2_all_job_end_talk_proc,
};
// clang-format on
rcn_guide2->talk_proc = proc[talk_proc_idx];
}
static void aNRG2_set_goods_talk_info(ACTOR* actorx) {
NPC_RCN_GUIDE2_ACTOR* rcn_guide2 = (NPC_RCN_GUIDE2_ACTOR*)actorx;
int msg_no = 0x081C;
/* Check if it's a raffle day */
if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) {
msg_no = 0x0833;
}
mDemo_Set_msg_num(msg_no);
mDemo_Set_talk_turn(TRUE);
rcn_guide2->talk_proc = (aNRG2_TALK_PROC)&none_proc1;
}
static int aNRG2_goods_talk_request(ACTOR* actorx, GAME* game) {
PLAYER_ACTOR* player = GET_PLAYER_ACTOR_GAME(game);
int res = FALSE;
if (player != NULL) {
int ux;
int uz;
mActor_name_t item;
mFI_Wpos2UtNum(&ux, &uz, player->forward_ut_pos);
item = Common_Get(clip).shop_design_clip->unitNum2ItemNo_proc(ux, uz);
if (player->a_btn_pressed == TRUE && item != EXIT_DOOR1 && item != EMPTY_NO && item != RSV_WALL_NO &&
item != RSV_NO && item != DOOR0) {
/* Player interacted with shop goods, tell them they're inaccessible currently */
NPC_RCN_GUIDE2_ACTOR* rcn_guide2 = (NPC_RCN_GUIDE2_ACTOR*)actorx;
mDemo_Request(mDemo_TYPE_SPEAK, actorx, &aNRG2_set_goods_talk_info);
rcn_guide2->talk_proc_idx = 0;
res = TRUE;
}
}
return res;
}
static int aNRG2_cloth_check(void) {
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int res = FALSE;
if (errand_p->base.quest_kind > mQst_ERRAND_FIRSTJOB_CHANGE_CLOTH &&
errand_p->info.first_job.wrong_cloth == FALSE && Now_Private->cloth.item != ITM_CLOTH016) {
/* Player changed out of work uniform on the job, now they get a stern talking to! */
res = TRUE;
}
return res;
}
static int aNRG2_check_upstair(void) {
PLAYER_ACTOR* player = GET_PLAYER_ACTOR_NOW();
u16 angle_y = player->actor_class.shape_info.rotation.y;
int res = FALSE;
if (angle_y > DEG2SHORT_ANGLE2(135.0f) && angle_y < DEG2SHORT_ANGLE2(225.0f) &&
player->item_in_front == RSV_POLICE_ITEM_0) {
res = TRUE;
}
return res;
}
static void aNRG2_set_force_talk_info(ACTOR* actorx) {
static aNRG2_talk_info_c dt_tbl[] = {
{ 0x07EE, &aNRG2_say_hello_talk_proc }, /* 'Well, finally you arrive!' */
{ 0x07EF, &aNRG2_say_hello_talk_proc }, /* 'So you're back again today?' */
{ 0x07EE, &aNRG2_say_hello_sp_talk_proc }, /* 'Well, finally you arrive!' (already wearing work uniform) */
{ 0x0832, &aNRG2_cloth_chk_talk_proc }, /* 'Why did you change out of your uniform, hm?' */
{ 0x0834, (aNRG2_TALK_PROC)&none_proc1 }, /* 'Stop right there!' (Going up to 2nd floor) */
};
aNRG2_talk_info_c* data;
NPC_RCN_GUIDE2_ACTOR* rcn_guide2 = (NPC_RCN_GUIDE2_ACTOR*)actorx;
mQst_errand_c* errand_p = mQst_GetFirstJobData();
int talk_idx;
/* Figure out our talk state */
if (aNRG2_cloth_check() == TRUE) {
talk_idx = aNRG2_FORCE_TALK_CLOTH_CHK; // Player changed out of their work uniform
errand_p->info.first_job.wrong_cloth = TRUE;
} else if (aNRG2_check_upstair() == TRUE) {
talk_idx = aNRG2_FORCE_TALK_UPSTAIR_CHK; // Player tried going upstairs in Nookington's
} else {
talk_idx = rcn_guide2->talk_idx;
}
data = &dt_tbl[talk_idx];
/* If assigning a new job then set the necessary text strings */
if (mQst_CheckFirstJobFin(errand_p) == FALSE) {
aNRG2_set_str_proc();
}
/* Apply the relevant data */
mDemo_Set_msg_num(data->msg_no);
mDemo_Set_talk_turn(TRUE);
rcn_guide2->talk_proc = data->talk_proc;
}
static void aNRG2_force_talk_request(ACTOR* actorx, GAME* game) {
NPC_RCN_GUIDE2_ACTOR* rcn_guide2 = (NPC_RCN_GUIDE2_ACTOR*)actorx;
mDemo_Request(mDemo_TYPE_SPEAK, actorx, &aNRG2_set_force_talk_info);
rcn_guide2->talk_proc_idx = 0;
}
static void aNRG2_set_norm_talk_info(ACTOR* actorx) {
// clang-format off
static aNRG2_talk_info_c dt_tbl[] = {
{ 0x07F1, &aNRG2_job_start_talk_proc },
{ 0x07F6, &aNRG2_job_start_talk_proc },
{ 0x07FB, &aNRG2_job_start_talk_proc },
{ 0x0802, &aNRG2_job_start_talk_proc },
{ 0x080C, &aNRG2_job_start_talk_proc },
{ 0x0830, &aNRG2_job_start_talk_proc },
{ 0x0813, &aNRG2_job_start_talk_proc },
{ 0x0818, &aNRG2_job_start_talk_proc },
{ 0x0821, &aNRG2_job_start_talk_proc },
{ 0x0827, &aNRG2_job_start_talk_proc },
{ 0x07F0, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x07F5, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x07FA, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x07FA, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x07FA, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x0826, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x07FA, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x0818, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x07F3, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x081F, &aNRG2_job_start_talk_proc },
{ 0x0835, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x07F8, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x07FE, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x07FF, &aNRG2_demo2_start_wait_talk_proc },
{ 0x0807, &aNRG2_check_more_paper_talk_proc },
{ 0x0808, &aNRG2_decide_new_target_talk_proc },
{ 0x0804, &aNRG2_give_new_paper_talk_proc },
{ 0x080F, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x0810, &aNRG2_demo2_start_wait_talk_proc },
{ 0x0815, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x0816, &aNRG2_demo3_start_wait_talk_proc },
{ 0x0819, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x0822, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x0829, (aNRG2_TALK_PROC)&none_proc1 },
{ 0x07F4, &aNRG2_job_end_talk_proc },
{ 0x07F9, &aNRG2_job_end_talk_proc },
{ 0x0801, &aNRG2_3rd_job_end_talk_proc },
{ 0x080B, &aNRG2_job_end_talk_proc },
{ 0x0812, &aNRG2_job_end_talk_proc },
{ 0x0818, &aNRG2_job_end_talk_proc },
{ 0x081A, &aNRG2_all_job_end_talk_proc },
{ 0x0828, &aNRG2_job_end_talk_proc },
{ 0x0830, &aNRG2_job_end_talk_proc },
{ 0x0836, (aNRG2_TALK_PROC)&none_proc1 },
};
// clang-format on
NPC_RCN_GUIDE2_ACTOR* rcn_guide2 = (NPC_RCN_GUIDE2_ACTOR*)actorx;
int talk_idx = rcn_guide2->talk_idx;
aNRG2_talk_info_c* data = &dt_tbl[talk_idx];
mQst_errand_c* errand_p = mQst_GetFirstJobData();
if (talk_idx >= aNRG2_NORM_TALK_J1_CONT1 && talk_idx <= aNRG2_NORM_TALK_J11_CONT1) {
rcn_guide2->can_ask_again_flag = TRUE;
}
if (mQst_CheckFirstJobFin(errand_p) == FALSE) {
aNRG2_set_str_proc();
}
mDemo_Set_msg_num(data->msg_no);
rcn_guide2->talk_proc = data->talk_proc;
}
static void aNRG2_norm_talk_request(ACTOR* actorx, GAME* game) {
NPC_RCN_GUIDE2_ACTOR* rcn_guide2 = (NPC_RCN_GUIDE2_ACTOR*)actorx;
if (aNRG2_goods_talk_request(actorx, game) == FALSE) {
if (aNRG2_cloth_check() == TRUE) {
aNRG2_force_talk_request(actorx, game);
} else if (aNRG2_check_upstair() == TRUE) {
aNRG2_force_talk_request(actorx, game);
} else {
mDemo_Request(mDemo_TYPE_TALK, actorx, &aNRG2_set_norm_talk_info);
rcn_guide2->talk_proc_idx = 0;
}
}
}
static int aNRG2_talk_init(ACTOR* actorx, GAME* game) {
NPC_RCN_GUIDE2_ACTOR* rcn_guide2 = (NPC_RCN_GUIDE2_ACTOR*)actorx;
rcn_guide2->npc_class.talk_info.talk_request_proc = (aNPC_TALK_REQUEST_PROC)&none_proc1;
mDemo_Set_ListenAble();
return TRUE;
}
static int aNRG2_talk_end_chk(ACTOR* actorx, GAME* game) {
NPC_RCN_GUIDE2_ACTOR* rcn_guide2 = (NPC_RCN_GUIDE2_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
int res = FALSE;
(*rcn_guide2->talk_proc)(rcn_guide2);
if (mDemo_Check(mDemo_TYPE_SPEAK, actorx) == FALSE && mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE) {
aNRG2_setup_think_proc(rcn_guide2, play, rcn_guide2->next_think_idx);
res = TRUE;
}
return res;
}
+39
View File
@@ -0,0 +1,39 @@
static int aNRG_set_request_act(NPC_RCN_GUIDE_ACTOR* rcn_guide, u8 act_prio, u8 act_idx, u8 act_type, u16 obj, int x,
int z) {
u16 args[6];
int res = FALSE;
if (act_prio >= rcn_guide->npc_class.request.act_priority) {
bzero(args, sizeof(args));
args[0] = obj;
args[2] = x;
args[3] = z;
rcn_guide->npc_class.request.act_priority = act_prio;
rcn_guide->npc_class.request.act_idx = act_idx;
rcn_guide->npc_class.request.act_type = act_type;
mem_copy((u8*)rcn_guide->npc_class.request.act_args, (u8*)args, sizeof(args));
res = TRUE;
}
return res;
}
static void aNRG_set_house_master_name(int house_idx) {
mMsg_SET_FREE_STR(mMsg_FREE_STR0, Save_Get(private_data[mHS_get_pl_no(house_idx)]).player_ID.player_name,
PLAYER_NAME_LEN);
}
static void aNRG_set_shop_address(NPC_RCN_GUIDE_ACTOR* rcn_guide) {
static u8 choume_str[] = { 'Q', 'A', 'B', 'C', 'D', 'E', 'F' };
u8 str[1];
/* Set the row (Z) string */
mMsg_SET_FREE_STR(mMsg_FREE_STR1, &choume_str[rcn_guide->shop_bz], 1);
/* Set the column (X) string */
mFont_UnintToString(str, sizeof(str), rcn_guide->shop_bx, sizeof(str), TRUE, FALSE, TRUE);
mMsg_SET_FREE_STR(mMsg_FREE_STR2, str, sizeof(str));
}
static void aNRG_actor_move(ACTOR* actorx, GAME* game) {
Common_Get(clip).npc_clip->move_proc(actorx, game);
}
@@ -0,0 +1,407 @@
typedef void (*aNRG_THINK_INIT_PROC)(NPC_RCN_GUIDE_ACTOR*, GAME_PLAY*);
typedef struct npc_rcn_guide_setup_think_s {
aNRG_THINK_PROC think_proc;
aNRG_THINK_INIT_PROC think_init_proc;
aNPC_TALK_REQUEST_PROC talk_request_proc;
u8 talk_idx;
u8 next_think_idx;
} aNRG_setup_think_c;
static void aNRG_approach(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
if (rcn_guide->npc_class.action.step == aNPC_ACTION_END_STEP && rcn_guide->npc_class.action.idx == 2) {
aNRG_setup_think_proc(rcn_guide, play, aNRG_THINK_INTRODUCE);
}
}
static void aNRG_turn(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
if (rcn_guide->npc_class.action.step == aNPC_ACTION_END_STEP && rcn_guide->npc_class.action.idx == 3) {
aNRG_setup_think_proc(rcn_guide, play, rcn_guide->next_think_idx);
}
}
static void aNRG_take_with(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
if (rcn_guide->npc_class.action.step == aNPC_ACTION_END_STEP && rcn_guide->npc_class.action.idx == 2) {
int path = rcn_guide->path;
if (path >= 1) {
aNRG_setup_think_proc(rcn_guide, play, aNRC_THINK_EXPLAIN);
} else {
aNRG_set_request_act(rcn_guide, 4, aNPC_ACT_WALK2, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, 2240,
1500);
path++;
}
rcn_guide->path = path;
}
}
static void aNRG_decide_house_wait(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
int next_think_idx = -1;
if (GET_PLAYER_ACTOR_NOW()->excute_cancel_wade) {
/* Player is trying to leave the acre, so let them know they can't */
next_think_idx = aNRC_THINK_STOP_WADE;
} else if (Common_Get(clip).demo_clip != NULL && Common_Get(clip).demo_clip->type == mDemo_CLIP_TYPE_INTRO_DEMO) {
ACTOR* demo_actor = (ACTOR*)Common_Get(clip).demo_clip->demo_class;
if (demo_actor != NULL) {
INTRO_DEMO_ACTOR* intro_demo = (INTRO_DEMO_ACTOR*)demo_actor;
switch (intro_demo->player_intro_demo_state) {
case 1:
next_think_idx = aNRC_THINK_BEFORE_OPEN_DOOR_TALK;
break;
case 2:
next_think_idx = aNRC_THINK_BEFORE_OPEN_DOOR_TALK2;
break;
}
}
}
if (next_think_idx >= 0) {
aNRG_setup_think_proc(rcn_guide, play, next_think_idx);
}
}
static void aNRG_enter_wait(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
if (Common_Get(clip).demo_clip != NULL && Common_Get(clip).demo_clip->type == mDemo_CLIP_TYPE_INTRO_DEMO) {
ACTOR* demo_actor = (ACTOR*)Common_Get(clip).demo_clip->demo_class;
if (demo_actor != NULL) {
INTRO_DEMO_ACTOR* intro_demo = (INTRO_DEMO_ACTOR*)demo_actor;
intro_demo->player_in_house = TRUE;
aNRG_setup_think_proc(rcn_guide, play, aNRC_THINK_WAIT);
}
}
}
static void aNRG_exit(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
static s16 moveX[] = { 2240, 2240, 2240, 2240 };
static s16 moveZ[] = { 1900, 1980, 1300, 1220 };
if (rcn_guide->npc_class.action.step == aNPC_ACTION_END_STEP) {
f32 posZ = rcn_guide->npc_class.actor_class.world.position.z;
int idx;
if (posZ < 1540.0f) {
if (posZ <= 1220.0f) {
idx = -1;
} else if (posZ <= 1300.0f) {
idx = 3;
} else {
idx = 2;
}
} else {
if (posZ >= 1980.0f) {
idx = -1;
} else if (posZ >= 1900.0f) {
idx = 1;
} else {
idx = 0;
}
}
if (idx == -1) {
if (Common_Get(clip).demo_clip != NULL && Common_Get(clip).demo_clip->type == mDemo_CLIP_TYPE_INTRO_DEMO) {
ACTOR* demo_actor = (ACTOR*)Common_Get(clip).demo_clip->demo_class;
if (demo_actor != NULL) {
INTRO_DEMO_ACTOR* intro_demo = (INTRO_DEMO_ACTOR*)demo_actor;
intro_demo->rcn_guide_actor_p = NULL;
Actor_delete(&rcn_guide->npc_class.actor_class);
play->submenu.start_refuse = FALSE;
}
}
} else {
aNRG_set_request_act(rcn_guide, 4, aNPC_ACT_WALK2, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, moveX[idx],
moveZ[idx]);
}
}
}
static void aNRG_restart_wait(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
int think_idx;
if (mPlib_check_player_actor_main_index_OutDoorMove2(&play->game) == FALSE) {
switch (rcn_guide->npc_class.actor_class.actor_specific) {
case 1:
think_idx = aNRC_THINK_DECIDE_HOUSE;
break;
default:
think_idx = aNRC_THINK_RESTART_TALK;
break;
}
aNRG_setup_think_proc(rcn_guide, play, think_idx);
}
}
static void aNRG_think_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
NPC_RCN_GUIDE_ACTOR* rcn_guide = (NPC_RCN_GUIDE_ACTOR*)nactorx;
(*rcn_guide->think_proc)(rcn_guide, play);
}
static void aNRG_think_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
NPC_RCN_GUIDE_ACTOR* rcn_guide = (NPC_RCN_GUIDE_ACTOR*)nactorx;
int think_idx;
switch (rcn_guide->npc_class.actor_class.actor_specific) {
case 1:
case 2:
think_idx = aNRC_THINK_RESTART_WAIT;
break;
default:
think_idx = aNRC_THINK_CALL;
break;
}
aNRG_setup_think_proc(rcn_guide, play, think_idx);
rcn_guide->npc_class.condition_info.hide_request = FALSE;
}
static void aNRG_call_init(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
s16 angle_y = atans_table(980.0f - rcn_guide->npc_class.actor_class.world.position.z,
2320.0f - rcn_guide->npc_class.actor_class.world.position.x);
rcn_guide->npc_class.actor_class.shape_info.rotation.y = angle_y;
rcn_guide->npc_class.actor_class.world.angle.y = angle_y;
}
static void aNRG_approach_init(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
PLAYER_ACTOR* player = GET_PLAYER_ACTOR(play);
f32 x;
f32 z;
/* Player cannot open the start menu */
play->submenu.start_refuse = TRUE;
/* Make the player stand around waiting */
mPlib_request_main_demo_wait_type1(&play->game, 0, NULL);
if (player != NULL) {
/* Move to a bit below where the player is */
x = player->actor_class.world.position.x;
z = player->actor_class.world.position.z + 70.0f;
} else {
/* Move to a predefined position -- how would the player even be NULL? */
x = 2320.0f;
z = 1050.0f;
}
/* Request action to move to desired location */
aNRG_set_request_act(rcn_guide, 4, aNPC_ACT_WALK2, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, x, z);
}
static void aNRG_introduce_init(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
aNRG_set_request_act(rcn_guide, 4, aNPC_ACT_WAIT, aNPC_ACT_TYPE_DEFAULT, aNPC_ACT_OBJ_DEFAULT, 0, 0);
}
static void aNRG_turn_init(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
mPlib_request_main_demo_wait_type1(&play->game, 0, NULL);
aNRG_set_request_act(rcn_guide, 4, aNPC_ACT_TURN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, 2240, 1300);
}
static void aNRG_take_with_init(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
if (Common_Get(clip).demo_clip != NULL && Common_Get(clip).demo_clip->type == mDemo_CLIP_TYPE_INTRO_DEMO) {
ACTOR* demo_actor = (ACTOR*)Common_Get(clip).demo_clip->demo_class;
if (demo_actor != NULL) {
INTRO_DEMO_ACTOR* intro_demo = (INTRO_DEMO_ACTOR*)demo_actor;
intro_demo->talk_flag = TRUE;
}
}
aNRG_set_request_act(rcn_guide, 4, aNPC_ACT_WALK2, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, 2240, 1300);
}
static void aNRG_before_open_door_talk2_init(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
INTRO_DEMO_ACTOR* intro_demo = (INTRO_DEMO_ACTOR*)Common_Get(clip).demo_clip->demo_class;
aNRG_set_house_master_name(intro_demo->house_idx);
}
static void aNRG_exit_turn_init(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
static s16 moveX[] = { 2240, 2240 };
static s16 moveZ[] = { 1900, 1300 };
int idx = 0;
if (rcn_guide->npc_class.actor_class.world.position.z < 1540.0f) {
idx = 1;
}
aNRG_set_request_act(rcn_guide, 4, aNPC_ACT_TURN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, moveX[idx],
moveZ[idx]);
if (Common_Get(clip).demo_clip != NULL && Common_Get(clip).demo_clip->type == mDemo_CLIP_TYPE_INTRO_DEMO) {
ACTOR* demo_actor = (ACTOR*)Common_Get(clip).demo_clip->demo_class;
if (demo_actor != NULL) {
INTRO_DEMO_ACTOR* intro_demo = (INTRO_DEMO_ACTOR*)demo_actor;
intro_demo->talk_flag = TRUE;
}
}
rcn_guide->next_think_idx = aNRC_THINK_EXIT;
}
static void aNRG_setup_think_proc(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play, int think_idx) {
// clang-format off
static aNRG_setup_think_c dt_tbl[] = {
{
(aNRG_THINK_PROC)&none_proc1,
&aNRG_call_init,
&aNRG_force_talk_request,
aNRG_FORCE_TALK_CALL,
aNRC_THINK_APPROACH,
},
{
&aNRG_approach,
&aNRG_approach_init,
(aNPC_TALK_REQUEST_PROC)&none_proc1,
aNRG_FORCE_TALK_CALL,
aNRC_THINK_APPROACH,
},
{
(aNRG_THINK_PROC)&none_proc1,
&aNRG_introduce_init,
&aNRG_force_talk_request,
aNRG_FORCE_TALK_INTRODUCE,
aNRC_THINK_TURN,
},
{
&aNRG_turn,
&aNRG_turn_init,
(aNPC_TALK_REQUEST_PROC)&none_proc1,
aNRG_FORCE_TALK_CALL,
aNRC_THINK_TAKE_WITH,
},
{
&aNRG_take_with,
&aNRG_take_with_init,
(aNPC_TALK_REQUEST_PROC)&none_proc1,
aNRG_FORCE_TALK_CALL,
aNRC_THINK_TAKE_WITH,
},
{
(aNRG_THINK_PROC)&none_proc1,
(aNRG_THINK_INIT_PROC)&none_proc1,
&aNRG_force_talk_request,
aNRG_FORCE_TALK_EXPLAIN,
aNRC_THINK_DECIDE_HOUSE_WAIT,
},
{
&aNRG_decide_house_wait,
&aNRG_introduce_init,
&aNRG_norm_talk_request,
aNRG_NORM_TALK_DECIDE_HOUSE,
aNRC_THINK_DECIDE_HOUSE_WAIT,
},
{
(aNRG_THINK_PROC)&none_proc1,
(aNRG_THINK_INIT_PROC)&none_proc1,
&aNRG_force_talk_request,
aNRG_FORCE_TALK_STOP_WADE,
aNRC_THINK_DECIDE_HOUSE_WAIT,
},
{
(aNRG_THINK_PROC)&none_proc1,
(aNRG_THINK_INIT_PROC)&none_proc1,
&aNRG_force_talk_request,
aNRG_FORCE_TALK_BEFORE_OPEN_DOOR_TALK,
aNRC_THINK_ENTER_WAIT,
},
{
(aNRG_THINK_PROC)&none_proc1,
&aNRG_before_open_door_talk2_init,
&aNRG_force_talk_request,
aNRG_FORCE_TALK_BEFORE_OPEN_DOOR2_TALK,
aNRC_THINK_ENTER_WAIT,
},
{
&aNRG_enter_wait,
(aNRG_THINK_INIT_PROC)&none_proc1,
(aNPC_TALK_REQUEST_PROC)&none_proc1,
aNRG_FORCE_TALK_CALL,
aNRC_THINK_ENTER_WAIT,
},
{
&aNRG_restart_wait,
(aNRG_THINK_INIT_PROC)&none_proc1,
(aNPC_TALK_REQUEST_PROC)&none_proc1,
aNRG_FORCE_TALK_CALL,
aNRC_THINK_RESTART_WAIT,
},
{
(aNRG_THINK_PROC)&none_proc1,
(aNRG_THINK_INIT_PROC)&none_proc1,
&aNRG_force_talk_request,
aNRG_FORCE_TALK_HOUSE_TAKEN,
aNRC_THINK_DECIDE_HOUSE_WAIT,
},
{
(aNRG_THINK_PROC)&none_proc1,
(aNRG_THINK_INIT_PROC)&none_proc1,
&aNRG_force_talk_request,
aNRG_FORCE_TALK_HOUSE_VACANT,
aNRC_THINK_DECIDE_HOUSE_WAIT,
},
{
&aNRG_turn,
&aNRG_exit_turn_init,
(aNPC_TALK_REQUEST_PROC)&none_proc1,
aNRG_FORCE_TALK_CALL,
aNRC_THINK_EXIT_TURN,
},
{
&aNRG_exit,
(aNRG_THINK_INIT_PROC)&none_proc1,
(aNPC_TALK_REQUEST_PROC)&none_proc1,
aNRG_FORCE_TALK_CALL,
aNRC_THINK_EXIT,
},
{
(aNRG_THINK_PROC)&none_proc1,
(aNRG_THINK_INIT_PROC)&none_proc1,
(aNPC_TALK_REQUEST_PROC)&none_proc1,
aNRG_FORCE_TALK_CALL,
aNRC_THINK_WAIT,
},
};
// clang-format on
aNRG_setup_think_c* think_data = &dt_tbl[think_idx];
rcn_guide->think_idx = think_idx;
rcn_guide->think_proc = think_data->think_proc;
rcn_guide->npc_class.talk_info.talk_request_proc = think_data->talk_request_proc;
rcn_guide->talk_idx = think_data->talk_idx;
rcn_guide->next_think_idx = think_data->next_think_idx;
(*think_data->think_init_proc)(rcn_guide, play);
}
static void aNRG_think_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) {
static aNPC_SUB_PROC think_proc[] = { &aNRG_think_init_proc, &aNRG_think_main_proc };
(*think_proc[type])(nactorx, play);
}
static void aNRG_schedule_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
nactorx->think.think_proc = &aNRG_think_proc;
Common_Get(clip).npc_clip->think_proc(nactorx, play, aNPC_THINK_SPECIAL, 0);
}
static void aNRG_schedule_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) {
int res = Common_Get(clip).npc_clip->think_proc(nactorx, play, -1, 1);
if (res == 0) {
Common_Get(clip).npc_clip->think_proc(nactorx, play, -1, 2);
}
}
static void aNRG_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) {
static aNPC_SUB_PROC sche_proc[] = { &aNRG_schedule_init_proc, &aNRG_schedule_main_proc };
(*sche_proc[type])(nactorx, play);
}
+170
View File
@@ -0,0 +1,170 @@
enum {
aNRG_TALK_DEMAND_PAYMENT,
aNRG_TALK_MENU_OPEN_WAIT,
aNRG_TALK_MENU_CLOSE_WAIT,
aNRG_TALK_DEMO_START_WAIT,
aNRG_TALK_DEMO_END_WAIT,
aNRG_TALK_FINISHED,
aNRG_TALK_NUM
};
static void aNRG_demand_payment_change_talk_proc(NPC_RCN_GUIDE_ACTOR* rcn_guide, int talk_proc_idx);
static void aNRG_demand_payment_talk_proc(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
u16 order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
if (order != 0) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
mMsg_REQUEST_MAIN_DISAPPEAR_WAIT_TYPE1();
aNRG_demand_payment_change_talk_proc(rcn_guide, aNRG_TALK_MENU_OPEN_WAIT);
}
}
static void aNRG_menu_open_wait_talk_proc(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
if (mMsg_CHECK_MAIN_WAIT() == TRUE) {
Submenu* submenu = &play->submenu;
int idx = mPr_GetPossessionItemIdxWithCond(Now_Private, ITM_MONEY_1000, mPr_ITEM_COND_QUEST);
mSM_open_submenu(submenu, mSM_OVL_INVENTORY, mSM_IV_OPEN_QUEST, idx);
mMsg_SET_LOCKCONTINUE();
aNRG_demand_payment_change_talk_proc(rcn_guide, aNRG_TALK_MENU_CLOSE_WAIT);
}
}
static void aNRG_menu_close_wait_talk_proc(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
Submenu* submenu = &play->submenu;
if (submenu->open_flag == FALSE) {
if (submenu->item_p->item == EMPTY_NO) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
mMsg_request_main_appear_wait_type1(msg_p);
mMsg_ChangeMsgData(msg_p, 0x07EB); /* 'You better pay it all back, or I will have to...' */
mMsg_Set_ForceNext(msg_p);
mMsg_Unset_LockContinue(msg_p);
aNRG_demand_payment_change_talk_proc(rcn_guide, aNRG_TALK_DEMAND_PAYMENT); /* Go back to first state */
} else {
aNRG_demand_payment_change_talk_proc(rcn_guide, aNRG_TALK_DEMO_START_WAIT); /* Handed over the Bells */
}
}
}
static void aNRG_demo_start_wait_talk_proc(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
if (Common_Get(clip).handOverItem_clip->request_mode == aHOI_REQUEST_TRANS_WAIT) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 1, 3);
aNRG_demand_payment_change_talk_proc(rcn_guide, aNRG_TALK_DEMO_END_WAIT);
}
}
static void aNRG_demo_end_wait_talk_proc(NPC_RCN_GUIDE_ACTOR* rcn_guide, GAME_PLAY* play) {
if (Common_Get(clip).handOverItem_clip->master_actor == NULL) {
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
aNRG_set_shop_address(rcn_guide);
rcn_guide->next_think_idx = aNRC_THINK_EXIT_TURN;
mMsg_request_main_appear_wait_type1(msg_p);
mMsg_Set_ForceNext(msg_p);
aNRG_demand_payment_change_talk_proc(rcn_guide, aNRG_TALK_FINISHED);
}
}
static void aNRG_demand_payment_change_talk_proc(NPC_RCN_GUIDE_ACTOR* rcn_guide, int talk_proc_idx) {
// clang-format off
static aNRG_TALK_PROC talk_proc[] = {
&aNRG_demand_payment_talk_proc,
&aNRG_menu_open_wait_talk_proc,
&aNRG_menu_close_wait_talk_proc,
&aNRG_demo_start_wait_talk_proc,
&aNRG_demo_end_wait_talk_proc,
(aNRG_TALK_PROC)&none_proc1,
};
// clang-format on
rcn_guide->talk_proc = talk_proc[talk_proc_idx];
}
static void aNRG_set_force_talk_info(ACTOR* actorx) {
// clang-format off
static aNRG_talk_data_c dt_tbl[] = {
{ 0x07DE, TRUE, CAMERA2_PROCESS_NORMAL, TRUE, (aNRG_TALK_PROC)&none_proc1 }, /* Step down from train station */
{ 0x07DF, TRUE, CAMERA2_PROCESS_TALK, FALSE, (aNRG_TALK_PROC)&none_proc1 }, /* Ask about call from Rover */
{ 0x07E1, TRUE, CAMERA2_PROCESS_TALK, FALSE, (aNRG_TALK_PROC)&none_proc1 }, /* Show houses */
{ 0x07E2, TRUE, CAMERA2_PROCESS_NORMAL, FALSE, (aNRG_TALK_PROC)&none_proc1 }, /* Player tries leaving acre */
{ 0x07E4, FALSE, CAMERA2_PROCESS_NORMAL, FALSE, (aNRG_TALK_PROC)&none_proc1 }, /* Player enters empty house */
{ 0x07E3, FALSE, CAMERA2_PROCESS_NORMAL, FALSE, (aNRG_TALK_PROC)&none_proc1 }, /* Player enters taken house */
{ 0x07E5, TRUE, CAMERA2_PROCESS_TALK, TRUE, (aNRG_TALK_PROC)&none_proc1 }, /* Player exits taken house */
{ 0x07E6, TRUE, CAMERA2_PROCESS_TALK, TRUE, &aNRG_demand_payment_talk_proc }, /* Player exits empty house */
};
// clang-format on
NPC_RCN_GUIDE_ACTOR* rcn_guide = (NPC_RCN_GUIDE_ACTOR*)actorx;
int talk_idx = rcn_guide->talk_idx;
aNRG_talk_data_c* data = &dt_tbl[talk_idx];
mDemo_Set_msg_num(data->msg_no);
mDemo_Set_talk_turn(data->turn_flag);
mDemo_Set_camera(data->camera_type);
rcn_guide->talk_proc_idx = aNRG_TALK_DEMAND_PAYMENT;
rcn_guide->talk_proc = data->talk_proc;
if (data->melody_flag == TRUE) {
rcn_guide->npc_class.talk_info.melody_inst = rcn_guide->melody_copy;
} else {
rcn_guide->npc_class.talk_info.melody_inst = 0;
}
if (talk_idx == 0) {
mBGMPsComp_make_ps_quiet(0);
}
}
static void aNRG_force_talk_request(ACTOR* actorx, GAME* game) {
mDemo_Request(mDemo_TYPE_SPEAK, actorx, &aNRG_set_force_talk_info);
}
static void aNRG_set_norm_talk_info(ACTOR* actorx) {
static aNRG_talk_data_c dt_tbl[] = {
{ 0x0820, TRUE, CAMERA2_PROCESS_TALK, FALSE, (aNRG_TALK_PROC)&none_proc1 }, /* Normal talk about houses */
};
NPC_RCN_GUIDE_ACTOR* rcn_guide = (NPC_RCN_GUIDE_ACTOR*)actorx;
aNRG_talk_data_c* data = &dt_tbl[rcn_guide->talk_idx];
mDemo_Set_msg_num(data->msg_no);
mDemo_Set_talk_turn(data->turn_flag);
mDemo_Set_camera(data->camera_type);
rcn_guide->talk_proc_idx = aNRG_TALK_DEMAND_PAYMENT;
rcn_guide->talk_proc = data->talk_proc;
if (data->melody_flag == TRUE) {
rcn_guide->npc_class.talk_info.melody_inst = rcn_guide->melody_copy;
} else {
rcn_guide->npc_class.talk_info.melody_inst = 0;
}
}
static void aNRG_norm_talk_request(ACTOR* actorx, GAME* game) {
mDemo_Request(mDemo_TYPE_TALK, actorx, &aNRG_set_norm_talk_info);
}
static int aNRG_talk_init(ACTOR* actorx, GAME* game) {
NPC_RCN_GUIDE_ACTOR* rcn_guide = (NPC_RCN_GUIDE_ACTOR*)actorx;
rcn_guide->npc_class.talk_info.talk_request_proc = (aNPC_TALK_REQUEST_PROC)&none_proc1;
mDemo_Set_ListenAble();
return TRUE;
}
static int aNRG_talk_end_chk(ACTOR* actorx, GAME* game) {
NPC_RCN_GUIDE_ACTOR* rcn_guide = (NPC_RCN_GUIDE_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
int res = FALSE;
(*rcn_guide->talk_proc)(rcn_guide, play);
if (mDemo_Check(mDemo_TYPE_SPEAK, actorx) == FALSE && mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE) {
/* We're done talking so move onto the next schedule step */
aNRG_setup_think_proc(rcn_guide, play, rcn_guide->next_think_idx);
res = TRUE;
}
return res;
}
+165
View File
@@ -0,0 +1,165 @@
#include "ac_npc_rtc.h"
#include "m_name_table.h"
#include "m_common_data.h"
#include "m_player_lib.h"
#include "jaudio_NES/staff.h"
#include "m_msg.h"
#include "m_bgm.h"
#include "m_soncho.h"
#include "m_card.h"
#include "boot.h"
#include "m_string.h"
#include "libultra/libultra.h"
#include "m_timeIn_ovl.h"
enum {
aNRTC_THINK_START,
aNRTC_THINK_TITLE,
aNRTC_THINK_DOOR,
aNRTC_THINK_CHECK,
aNRTC_THINK_IPMENU,
aNRTC_THINK_WAIT,
aNRTC_THINK_NUM
};
enum {
aNRTC_TALK_BREAK_DATA,
aNRTC_TALK_BREAK_DATA2,
aNRTC_TALK_RTC_ERR,
aNRTC_TALK_TIMER_OPEN_MSG_WAIT,
aNRTC_TALK_TIMER_OPEN_WAIT,
aNRTC_TALK_TIMER_CLOSE_WAIT,
aNRTC_TALK_DELETE_BF,
aNRTC_TALK_DELETE,
aNRTC_TALK_FORMAT_CHK,
aNRTC_TALK_FORMAT,
aNRTC_TALK_END,
aNRTC_TALK_NUM
};
static void aNRTC_actor_ct(ACTOR*, GAME*);
static void aNRTC_actor_dt(ACTOR*, GAME*);
static void aNRTC_actor_init(ACTOR*, GAME*);
static void aNRTC_actor_save(ACTOR*, GAME*);
// clang-format off
ACTOR_PROFILE Npc_Rtc_Profile = {
mAc_PROFILE_NPC_RTC,
ACTOR_PART_NPC,
ACTOR_STATE_NONE,
SP_NPC_RTC,
ACTOR_OBJ_BANK_KEEP,
sizeof(NPC_RTC_ACTOR),
&aNRTC_actor_ct,
&aNRTC_actor_dt,
&aNRTC_actor_init,
mActor_NONE_PROC1,
&aNRTC_actor_save,
};
static void aNRTC_actor_move(ACTOR*, GAME*);
static void aNRTC_actor_draw(ACTOR*, GAME*);
static int aNRTC_talk_init(ACTOR*, GAME*);
static int aNRTC_talk_end_chk(ACTOR*, GAME*);
static void aNRTC_schedule_proc(NPC_ACTOR*, GAME_PLAY*, int);
static void aNRTC_talk_request(ACTOR* actor, GAME*);
static void aNRTC_change_talk_proc(NPC_RTC_ACTOR* rtc, int idx);
static u8 aNRTC_sound_mode[] = { Config_SOUND_MODE_STEREO, Config_SOUND_MODE_MONO, Config_SOUND_MODE_HEADPHONES };
static u8 aNRTC_voice_mode[] = { Config_VOICE_MODE_ANIMALESE, Config_VOICE_MODE_CLICK, Config_VOICE_MODE_SILENT };
static void aNRTC_actor_ct(ACTOR* actor, GAME* game) {
// clang-format off
static aNPC_ct_data_c ct_data = {
&aNRTC_actor_move,
&aNRTC_actor_draw,
5,
mActor_NONE_PROC1,
&aNRTC_talk_init,
&aNRTC_talk_end_chk,
0,
};
// clang-format on
NPC_RTC_ACTOR* rtc = (NPC_RTC_ACTOR*)actor;
GAME_PLAY* play = (GAME_PLAY*)game;
PLAYER_ACTOR* player;
xyz_t center;
xyz_t eye;
if (Common_Get(clip.npc_clip)->birth_check_proc(actor, game) == TRUE) {
rtc->npc_class.schedule.schedule_proc = &aNRTC_schedule_proc;
Common_Get(clip.npc_clip)->ct_proc(actor, game, &ct_data);
actor->status_data.weight = MASSTYPE_IMMOVABLE;
mPlib_request_main_demo_wait_type1(game, 0, NULL);
player = GET_PLAYER_ACTOR(play);
if (player != NULL) {
player->actor_class.state_bitfield |= ACTOR_STATE_INVISIBLE;
}
center.x = 100.0f;
center.y = 60.0f;
center.z = 60.0f;
eye.x = 100.0f;
eye.y = 130.0f;
eye.z = 210.0f;
Camera2_change_priority(play, 0);
Camera2_request_main_lock(play, &center, &eye, 40.0f, 0, 100.0f, 400.0f, 5);
sAdo_SetOutMode(aNRTC_sound_mode[Save_Get(config.sound_mode)]);
sAdo_SetVoiceMode(aNRTC_voice_mode[Save_Get(config.voice_mode)]);
rtc->npc_class.condition_info.hide_request = 0;
rtc->npc_class.talk_info.default_act = 9;
rtc->npc_class.talk_info.melody_inst = 0;
rtc->talk_flag = FALSE;
}
}
static void aNRTC_actor_save(ACTOR* actor, GAME* game) {
Common_Get(clip.npc_clip)->save_proc(actor, game);
}
static void aNRTC_actor_dt(ACTOR* actor, GAME* game) {
Common_Get(clip.npc_clip)->dt_proc(actor, game);
}
static void aNRTC_actor_init(ACTOR* actor, GAME* game) {
Common_Get(clip.npc_clip)->init_proc(actor, game);
}
static void aNRTC_actor_move(ACTOR* actor, GAME* game) {
StaffRollInfo_c info;
f32 val = 0.5f;
u8 arm_flag = TRUE;
NPC_RTC_ACTOR* rtc = (NPC_RTC_ACTOR*)actor;
GAME_PLAY* play = (GAME_PLAY*)game;
if (rtc->npc_class.draw.animation_id == aNPC_ANIM_4HAKU_E1) {
sAdos_GetStaffRollInfo(&info);
if (info.staffroll_part != STAFFROLL_PART_FINISH) {
val = 0.0f;
arm_flag = FALSE;
rtc->npc_class.draw.main_animation.keyframe.frame_control.current_frame =
1.0f + (64.0f * (f32)info.percent);
}
}
rtc->npc_class.draw.main_animation.keyframe.frame_control.speed = val;
sAdos_TTKK_ARM(arm_flag);
Common_Get(clip.npc_clip)->move_proc(actor, game);
mSC_change_player_freeze(play);
}
static void aNRTC_actor_draw(ACTOR* actor, GAME* game) {
Common_Get(clip.npc_clip)->draw_proc(actor, game);
}
#include "../src/actor/ac_npc_rtc_think.c.inc"
#include "../src/actor/ac_npc_rtc_talk.c.inc"
+321
View File
@@ -0,0 +1,321 @@
static void aNRTC_set_slot_name(int slot_id, int str_no) {
u8 name[mIN_ITEM_NAME_LEN];
mString_Load_StringFromRom(name, sizeof(name), 0x06CD + slot_id);
mMsg_SET_FREE_STR(str_no, name, sizeof(name));
}
static void aNRTC_rtc_err(NPC_RTC_ACTOR* rtc, GAME_PLAY* play) {
if (mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0:
aNRTC_change_talk_proc(rtc, aNRTC_TALK_TIMER_OPEN_MSG_WAIT);
break;
case mChoice_CHOICE1:
rtc->think_idx = aNRTC_THINK_TITLE;
aNRTC_change_talk_proc(rtc, aNRTC_TALK_END);
break;
}
}
}
static void aNRTC_timer_open_msg_wait(NPC_RTC_ACTOR* rtc, GAME_PLAY* play) {
int order = mDemo_Get_OrderValue(mDemo_TYPE_4, 9);
if (order == 1) {
if (mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
mDemo_Set_OrderValue(mDemo_TYPE_4, 9, 0);
aNRTC_change_talk_proc(rtc, aNRTC_TALK_TIMER_OPEN_WAIT);
mMsg_REQUEST_MAIN_DISAPPEAR_WAIT_TYPE1();
}
}
}
static void aNRTC_timer_open_wait(NPC_RTC_ACTOR* rtc, GAME_PLAY* play) {
Submenu* submenu = &play->submenu;
if (mMsg_CHECK_MAIN_WAIT() == TRUE) {
aNRTC_change_talk_proc(rtc, aNRTC_THINK_WAIT);
mSM_open_submenu(submenu, mSM_OVL_TIMEIN, mTI_OVL_OPEN_INITIAL, 0);
mMsg_REQUEST_MAIN_APPEAR_WAIT_TYPE1();
}
}
static void aNRTC_timer_close_wait(NPC_RTC_ACTOR* rtc, GAME_PLAY* play) {
if (play->submenu.open_flag == FALSE) {
if (mMsg_CHECK_NOT_SERIES_MAIN_WAIT() == TRUE) {
mMsg_SET_FORCENEXT();
rtc->think_idx = aNRTC_THINK_DOOR;
aNRTC_change_talk_proc(rtc, aNRTC_TALK_END);
}
}
}
static void aNRTC_delete_bf(NPC_RTC_ACTOR* rtc, GAME_PLAY* play) {
int order = mDemo_Get_OrderValue(mDemo_TYPE_4, 9);
if ((mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) && (order != 0)) {
mMsg_SET_LOCKCONTINUE();
aNRTC_change_talk_proc(rtc, aNRTC_TALK_DELETE);
}
}
static void aNRTC_delete(NPC_RTC_ACTOR* rtc, GAME_PLAY* play) {
mMsg_Window_c* window;
int card;
int card_ret;
window = mMsg_Get_base_window_p();
card_ret = mCD_EraseBrokenLand_bg(&card);
switch (card_ret) {
case 0:
rtc->think_idx = aNRTC_THINK_CHECK;
mMsg_Set_continue_msg_num(window, 0x09DE);
break;
case 22:
case 2:
rtc->think_idx = aNRTC_THINK_TITLE;
mMsg_Set_continue_msg_num(window, 0x09DF);
break;
case 25:
return;
case 15:
rtc->think_idx = aNRTC_THINK_CHECK;
mMsg_Set_continue_msg_num(window, 0x09E1);
break;
default:
rtc->think_idx = aNRTC_THINK_TITLE;
mMsg_Set_continue_msg_num(window, 0x09DF);
break;
}
if (card_ret != 25) {
mMsg_Unset_LockContinue(window);
aNRTC_change_talk_proc(rtc, aNRTC_TALK_END);
}
}
static void aNRTC_format_chk(NPC_RTC_ACTOR* rtc, GAME_PLAY* play) {
if (mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
aNRTC_change_talk_proc(rtc, aNRTC_TALK_END);
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0:
rtc->think_idx = aNRTC_THINK_CHECK;
break;
case mChoice_CHOICE1:
rtc->think_idx = aNRTC_THINK_DOOR;
break;
case mChoice_CHOICE2:
rtc->think_idx = aNRTC_THINK_TITLE;
break;
case mChoice_CHOICE3:
rtc->think_idx = aNRTC_THINK_CHECK;
aNRTC_change_talk_proc(rtc, aNRTC_TALK_FORMAT);
break;
}
}
}
static void aNRTC_format(NPC_RTC_ACTOR* rtc, GAME_PLAY* play) {
int order;
mMsg_Window_c* window;
window = mMsg_Get_base_window_p();
order = mDemo_Get_OrderValue(mDemo_TYPE_4, 9);
switch (order) {
case 1:
mDemo_Set_OrderValue(mDemo_TYPE_4, 9, 2);
mMsg_Set_LockContinue(window);
break;
case 2:
switch (mCD_card_format_bg(Common_Get(memcard_slot))) {
case mCD_RESULT_SUCCESS:
mMsg_Set_continue_msg_num(window, 0x09E9);
mMsg_Unset_LockContinue(window);
aNRTC_change_talk_proc(rtc, aNRTC_TALK_END);
rtc->think_idx = aNRTC_THINK_CHECK;
mDemo_Set_OrderValue(mDemo_TYPE_4, 9, 0);
break;
case mCD_RESULT_ERROR:
mMsg_Unset_LockContinue(window);
aNRTC_change_talk_proc(rtc, aNRTC_TALK_END);
rtc->think_idx = aNRTC_THINK_TITLE;
mMsg_Set_continue_msg_num(window, 0x09E7);
mDemo_Set_OrderValue(mDemo_TYPE_4, 9, 0);
case mCD_RESULT_BUSY:
break;
}
break;
}
}
static void aNRTC_break_data(NPC_RTC_ACTOR* rtc, GAME_PLAY* play) {
if (mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
aNRTC_change_talk_proc(rtc, aNRTC_TALK_END);
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0:
rtc->think_idx = aNRTC_THINK_CHECK;
break;
case mChoice_CHOICE1:
aNRTC_change_talk_proc(rtc, aNRTC_TALK_DELETE_BF);
break;
}
}
}
static void aNRTC_break_data_2(NPC_RTC_ACTOR* rtc, GAME_PLAY* play) {
if (mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) {
aNRTC_change_talk_proc(rtc, aNRTC_TALK_END);
switch (mChoice_GET_CHOSENUM()) {
case mChoice_CHOICE0:
rtc->think_idx = aNRTC_THINK_CHECK;
break;
case mChoice_CHOICE1:
rtc->think_idx = aNRTC_THINK_DOOR;
break;
case mChoice_CHOICE2:
rtc->think_idx = aNRTC_THINK_TITLE;
break;
case mChoice_CHOICE3:
rtc->think_idx = aNRTC_THINK_IPMENU;
break;
}
}
}
static void aNRTC_change_talk_proc(NPC_RTC_ACTOR* rtc, int idx) {
// clang-format off
static aNRTC_PROC process[] = {
&aNRTC_break_data,
&aNRTC_break_data_2,
&aNRTC_rtc_err,
&aNRTC_timer_open_msg_wait,
&aNRTC_timer_open_wait,
&aNRTC_timer_close_wait,
&aNRTC_delete_bf,
&aNRTC_delete,
&aNRTC_format_chk,
&aNRTC_format,
(aNRTC_PROC)&none_proc1,
};
// clang-format on
rtc->talk_idx = idx;
rtc->talk_proc = process[idx];
}
static void aNRTC_set_talk_info_talk_request() {
int msg;
switch (Common_Get(save_error_type)) {
case mFRm_ERROR_BAD_RTC:
msg = 0x09CC;
break;
case mFRm_ERROR_DATA_CORRUPTED:
msg = 0x09D1;
break;
case mFRm_ERROR_MEMCARD_INVALID:
msg = 0x09DA;
break;
case mFRm_ERROR_MEMCARD_NO_SPACE:
msg = 0x09D8;
break;
case mFRm_ERROR_NO_MEMCARD:
msg = 0x09D4;
break;
case mFRm_ERROR_MEMCARD_TRAVELDATA_CONFLICT:
msg = 0x09E2;
break;
case mFRm_ERROR_MEMCARD_DAMAGED:
msg = 0x09E4;
break;
case mFRm_ERROR_MEMCARD_NO_FILES:
msg = 0x09E3;
break;
case mFRm_ERROR_MEMCARD_FORMAT:
msg = 0x09E5;
break;
case mFRm_ERROR_NOT_MEMCARD:
msg = 0x09E6;
break;
default:
msg = 0x09D4;
break;
}
mDemo_Set_msg_num(msg);
mDemo_Set_camera(CAMERA2_PROCESS_NORMAL);
}
static void aNRTC_talk_request(ACTOR* actor, GAME* game) {
mDemo_Request(mDemo_TYPE_SPEAK, actor, &aNRTC_set_talk_info_talk_request);
}
static int aNRTC_talk_init(ACTOR* actor, GAME* game) {
NPC_RTC_ACTOR* rtc = (NPC_RTC_ACTOR*)actor;
mDemo_Set_ListenAble();
aNRTC_set_slot_name(Common_Get(memcard_slot), mMsg_FREE_STR4);
switch (Common_Get(save_error_type)) {
case mFRm_ERROR_BAD_RTC:
aNRTC_change_talk_proc(rtc, aNRTC_TALK_RTC_ERR);
break;
case mFRm_ERROR_DATA_CORRUPTED:
aNRTC_change_talk_proc(rtc, aNRTC_TALK_BREAK_DATA);
break;
case mFRm_ERROR_MEMCARD_FORMAT:
aNRTC_change_talk_proc(rtc, aNRTC_TALK_FORMAT_CHK);
break;
default:
aNRTC_change_talk_proc(rtc, aNRTC_TALK_BREAK_DATA2);
break;
}
rtc->npc_class.talk_info.talk_request_proc = mActor_NONE_PROC1;
mMsg_SET_IDLING_REQ();
return TRUE;
}
static int aNRTC_talk_end_chk(ACTOR* actor, GAME* game) {
NPC_RTC_ACTOR* rtc = (NPC_RTC_ACTOR*)actor;
GAME_PLAY* play = (GAME_PLAY*)game;
int res = FALSE;
mMsg_Window_c* window;
window = mMsg_Get_base_window_p();
(*rtc->talk_proc)(rtc, play);
if (mMsg_Check_idling_now(window) == TRUE) {
mMsg_request_main_disappear_wait_type1(window);
aNRTC_think_init_proc(&rtc->npc_class, play);
rtc->talk_flag = FALSE;
res = TRUE;
rtc->bgm_timer = 50;
rtc->fade_timer = 75;
bzero(&play->fade_color_value, sizeof(rgba8888_t));
} else {
int counter = rtc->counter;
if ((mMsg_CHECK_MAINNORMAL() == TRUE) || (mChoice_CHECK_MAIN_NORMAL() == TRUE)) {
counter++;
if (counter > 600) {
counter = 600;
}
} else {
counter = 0;
}
if (mDemo_Get_OrderValue(mDemo_TYPE_4, 0) == 0) {
if (counter >= 600) {
if (rtc->npc_class.draw.animation_id != aNPC_ANIM_4HAKU_E1) {
mDemo_Set_OrderValue(mDemo_TYPE_4, 0, 0xFF);
}
} else if (rtc->npc_class.draw.animation_id == aNPC_ANIM_4HAKU_E1) {
mDemo_Set_OrderValue(mDemo_TYPE_4, 0, 0xFD);
}
}
rtc->counter = counter;
}
return res;
}
+141
View File
@@ -0,0 +1,141 @@
static void aNRTC_talk_request(ACTOR* actor, GAME*);
static void aNRTC_think_start(NPC_ACTOR* actor, GAME_PLAY* play) {
NPC_RTC_ACTOR* rtc = (NPC_RTC_ACTOR*)actor;
if (rtc->first_talk_timer > 0) {
rtc->first_talk_timer--;
} else {
rtc->talk_flag = TRUE;
rtc->npc_class.talk_info.talk_request_proc = &aNRTC_talk_request;
rtc->npc_class.condition_info.demo_flg = aNPC_COND_DEMO_SKIP_HEAD_LOOKAT;
}
}
static void aNRTC_think_title(NPC_ACTOR* actor, GAME_PLAY* play) {
NPC_RTC_ACTOR* rtc = (NPC_RTC_ACTOR*)actor;
play->fb_wipe_type = 3;
play->fb_fade_type = 4;
mPlib_request_main_invade_type1((GAME*)play);
Actor_info_save_actor(play);
rtc->think_idx = aNRTC_THINK_WAIT;
}
// clang-format off
static Door_data_c door_data = {
SCENE_PLAYERSELECT,
mSc_DIRECT_NORTH,
FALSE,
0,
{ 100, 0, 120 },
EMPTY_NO,
3,
{ 0, 0, 0 },
};
// clang-format on
static void aNRTC_think_door(NPC_ACTOR* actor, GAME_PLAY* play) {
if (sAdo_BgmFadeoutCheck() != 0) {
goto_other_scene(play, &door_data, 1);
Common_Set(transition.wipe_type, 3);
}
}
static void aNRTC_think_check(NPC_ACTOR* actor, GAME_PLAY* play) {
NPC_RTC_ACTOR* rtc = (NPC_RTC_ACTOR*)actor;
if (sAdo_BgmFadeoutCheck() != 0) {
goto_other_scene(play, &door_data, 1);
mCD_ReCheckLoadLand(play);
Common_Set(transition.wipe_type, 3);
rtc->think_idx = aNRTC_THINK_WAIT;
}
}
static void aNRTC_think_ipmenu(NPC_ACTOR* actor, GAME_PLAY* play) {
NPC_RTC_ACTOR* rtc = (NPC_RTC_ACTOR*)actor;
if (sAdo_BgmFadeoutCheck() != 0) {
HotResetIplMenu();
rtc->think_idx = aNRTC_THINK_WAIT;
}
}
// clang-format off
static aNPC_SUB_PROC aNRTC_proc_table[] = {
&aNRTC_think_start,
&aNRTC_think_title,
&aNRTC_think_door,
&aNRTC_think_check,
&aNRTC_think_ipmenu,
(aNPC_SUB_PROC)mActor_NONE_PROC1,
};
// clang-format on
static void aNRTC_think_main_proc(NPC_ACTOR* actor, GAME_PLAY* play) {
NPC_RTC_ACTOR* rtc = (NPC_RTC_ACTOR*)actor;
if (rtc->fade_timer > 0) {
rtc->fade_timer--;
if (rtc->fade_timer == 0) {
play->fade_color_value.c.a = -1;
} else if (rtc->fade_timer < 25) {
play->fade_color_value.c.a = 255.0f * (1.0f - (0.04f * rtc->fade_timer));
}
} else if (rtc->talk_flag == 0) {
aNRTC_proc_table[rtc->think_idx](actor, play);
}
if (rtc->bgm_timer == 0) {
if (rtc->think_idx == 1) {
mBGMPsComp_make_ps_wipe(0x21C2);
} else {
mBGMPsComp_make_ps_wipe(0x621C);
}
rtc->bgm_timer = -2;
} else if (rtc->bgm_timer > 0) {
rtc->bgm_timer--;
}
}
static void aNRTC_think_init_proc(NPC_ACTOR* actor, GAME_PLAY* play) {
NPC_RTC_ACTOR* rtc = (NPC_RTC_ACTOR*)actor;
rtc->npc_class.request.act_priority = 4;
rtc->npc_class.request.act_idx = 8;
rtc->npc_class.request.act_type = 0;
}
static void aNRTC_think_proc(NPC_ACTOR* actor, GAME_PLAY* play, int idx) {
static aNPC_SUB_PROC think_proc[] = {
&aNRTC_think_init_proc,
&aNRTC_think_main_proc,
};
think_proc[idx](actor, play);
}
static void aNRTC_schedule_init_proc(NPC_ACTOR* actor, GAME_PLAY* play) {
NPC_RTC_ACTOR* rtc = (NPC_RTC_ACTOR*)actor;
rtc->npc_class.draw._5BE = 1;
rtc->npc_class.talk_info.default_animation = aNPC_ANIM_4HAKU_E1;
rtc->bgm_timer = -1;
rtc->fade_timer = 0;
rtc->first_talk_timer = 90;
rtc->npc_class.think.think_proc = aNRTC_think_proc;
rtc->think_idx = 0;
Common_Get(clip.npc_clip)->think_proc(actor, play, aNPC_THINK_IN_BLOCK, 0);
}
static void aNRTC_schedule_main_proc(NPC_ACTOR* actor, GAME_PLAY* play) {
NPC_RTC_ACTOR* rtc = (NPC_RTC_ACTOR*)actor;
if (Common_Get(clip.npc_clip)->think_proc(actor, play, -1, 1) == 0) {
Common_Get(clip.npc_clip)->think_proc(actor, play, -1, 2);
}
}
static void aNRTC_schedule_proc(NPC_ACTOR* actor, GAME_PLAY* play, int idx) {
static aNPC_SUB_PROC sche_proc[] = {
&aNRTC_schedule_init_proc,
&aNRTC_schedule_main_proc,
};
sche_proc[idx](actor, play);
}
+85
View File
@@ -0,0 +1,85 @@
#include "ac_npc_sendo.h"
#include "m_common_data.h"
#include "ac_boat_demo.h"
#include "sys_matrix.h"
#include "m_msg.h"
#include "libultra/libultra.h"
#include "GBA2/gba2.h"
#include "m_ledit_ovl.h"
static void aSEN_actor_ct(ACTOR* actorx, GAME* game);
static void aSEN_actor_dt(ACTOR* actorx, GAME* game);
static void aSEN_actor_init(ACTOR* actorx, GAME* game);
static void aSEN_actor_move(ACTOR* actorx, GAME* game);
static void aSEN_actor_draw(ACTOR* actorx, GAME* game);
static void aSEN_actor_save(ACTOR* actorx, GAME* game);
ACTOR_PROFILE Npc_Sendo_Profile = {
mAc_PROFILE_NPC_SENDO,
ACTOR_PART_NPC,
ACTOR_STATE_NONE,
SP_NPC_SENDO,
ACTOR_OBJ_BANK_KEEP,
sizeof(NPC_SENDO_ACTOR),
&aSEN_actor_ct,
&aSEN_actor_dt,
&aSEN_actor_init,
mActor_NONE_PROC1,
&aSEN_actor_save
};
static int aSEN_talk_init(ACTOR*, GAME*);
static int aSEN_talk_end_chk(ACTOR*, GAME*);
static void aSEN_schedule_proc(NPC_ACTOR*, GAME_PLAY*, int);
static void aSEN_setup_think_proc(NPC_SENDO_ACTOR*, GAME_PLAY*, u8);
static MtxF aSEN_matrix;
static void aSEN_actor_ct(ACTOR* actorx, GAME* game) {
static aNPC_ct_data_c ct_data = {
&aSEN_actor_move,
&aSEN_actor_draw,
5,
(aNPC_TALK_REQUEST_PROC)&none_proc1,
&aSEN_talk_init,
&aSEN_talk_end_chk,
0
};
if ((*Common_Get(clip).npc_clip->birth_check_proc)(actorx, game) == TRUE) {
NPC_ACTOR* npc_actor = (NPC_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
npc_actor->schedule.schedule_proc = &aSEN_schedule_proc;
(*Common_Get(clip).npc_clip->ct_proc)(actorx, game, &ct_data);
}
}
static void aSEN_actor_save(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->save_proc)(actorx, game);
}
static void aSEN_actor_dt(ACTOR* actorx, GAME* game) {
NPC_SENDO_ACTOR* sendo = (NPC_SENDO_ACTOR*)actorx;
BOAT_DEMO_ACTOR* boat_demo;
(*Common_Get(clip).npc_clip->dt_proc)(actorx, game);
boat_demo = (BOAT_DEMO_ACTOR*)actorx->parent_actor;
if (boat_demo != NULL && boat_demo->npc_sendo_actor == sendo) {
boat_demo->npc_sendo_actor = NULL;
}
}
static void aSEN_actor_init(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->init_proc)(actorx, game);
}
static void aSEN_actor_draw(ACTOR* actorx, GAME* game) {
Matrix_put(&aSEN_matrix);
(*Common_Get(clip).npc_clip->draw_proc)(actorx, game);
}
#include "../src/actor/ac_npc_sendo_move.c_inc"
File diff suppressed because it is too large Load Diff
+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/actor/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);
}
+89
View File
@@ -0,0 +1,89 @@
#include "ac_ev_castaway.h"
#include "m_common_data.h"
static void aECST_actor_ct(ACTOR* actorx, GAME* game);
static void aECST_actor_dt(ACTOR* actorx, GAME* game);
static void aECST_actor_init(ACTOR* actorx, GAME* game);
static void aECST_actor_move(ACTOR* actorx, GAME* game);
static void aECST_actor_draw(ACTOR* actorx, GAME* game);
static void aECST_actor_save(ACTOR* actorx, GAME* game);
ACTOR_PROFILE Ev_Castaway_Profile = {
mAc_PROFILE_EV_CASTAWAY,
ACTOR_PART_NPC,
ACTOR_STATE_CAN_MOVE_IN_DEMO_SCENES | ACTOR_STATE_NO_MOVE_WHILE_CULLED,
EMPTY_NO,
ACTOR_OBJ_BANK_KEEP,
sizeof(EV_CASTAWAY_ACTOR),
&aECST_actor_ct,
&aECST_actor_dt,
&aECST_actor_init,
mActor_NONE_PROC1,
&aECST_actor_save,
};
static void aECST_schedule_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int type);
static void aECST_actor_ct(ACTOR* actorx, GAME* game) {
static aNPC_ct_data_c ct_data = { &aECST_actor_move, &aECST_actor_draw, 5, NULL, NULL, NULL, 0 };
static xyz_t def_pos = { 3580.0f, 0.0f, 4670.0f }; // 'G-5' @ 9-4
EV_CASTAWAY_ACTOR* castaway = (EV_CASTAWAY_ACTOR*)actorx;
if ((*Common_Get(clip).npc_clip->birth_check_proc)(actorx, game) == TRUE) {
castaway->npc_class.schedule.schedule_proc = &aECST_schedule_proc;
(*Common_Get(clip).npc_clip->ct_proc)(actorx, game, &ct_data);
castaway->npc_class.condition_info.demo_flg = ~aNPC_COND_DEMO_SKIP_MOVE_Y; // is this a mistake?
castaway->npc_class.condition_info.hide_request = FALSE;
castaway->npc_class.palActorIgnoreTimer = -1;
aNPC_SPNPC_BIT_SET(Common_Get(spnpc_first_talk_flags), aNPC_SPNPC_BIT_DOZAEMON);
actorx->status_data.weight = 254;
actorx->gravity = 0.0f;
actorx->max_velocity_y = 0.0f;
actorx->shape_info.rotation.y = DEG2SHORT_ANGLE(68.027344f); // 0x3060
actorx->world.angle.y = DEG2SHORT_ANGLE(68.027344f); // 0x3060
castaway->npc_class.movement.mv_angl = DEG2SHORT_ANGLE(68.027344f); // 0x3060
actorx->world.position = def_pos;
actorx->home.position = def_pos;
}
}
static void aECST_actor_save(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->save_proc)(actorx, game);
}
static void aECST_actor_dt(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->dt_proc)(actorx, game);
}
static void aECST_actor_init(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->init_proc)(actorx, game);
}
static void aECST_schedule_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play) {
if (actorx->draw.animation_id != 116) {
(*Common_Get(clip).npc_clip->animation_init_proc)((ACTOR*)actorx, aNPC_ANIM_GETUP_WAIT_SEG1, 0);
}
}
static void aECST_schedule_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int type) {
static aNPC_SUB_PROC sche_proc[2] = { (aNPC_SUB_PROC)&none_proc1, aECST_schedule_main_proc };
(*sche_proc[type])(actorx, play);
}
static void aECST_actor_move(ACTOR* actorx, GAME* game) {
EV_CASTAWAY_ACTOR* castaway = (EV_CASTAWAY_ACTOR*)actorx;
s16 cycle = castaway->bobbing_cycle;
cycle += 512;
actorx->position_speed.y = (actorx->home.position.y + 4.0f + sin_s(cycle) * 4.0f) - actorx->world.position.y;
castaway->bobbing_cycle = cycle;
(*Common_Get(clip).npc_clip->move_proc)(actorx, game);
}
static void aECST_actor_draw(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->draw_proc)(actorx, game);
}
+62
View File
@@ -0,0 +1,62 @@
#include "ac_ev_dokutu.h"
#include "m_common_data.h"
#include "../src/actor/ac_ev_dokutu_talk.c_inc"
static void aEVD_actor_ct(ACTOR* actorx, GAME* game);
static void aEVD_actor_dt(ACTOR* actorx, GAME* game);
static void aEVD_actor_init(ACTOR* actorx, GAME* game);
static void aEVD_actor_save(ACTOR* actorx, GAME* game);
static void aEVD_actor_move(ACTOR* actorx, GAME* game);
static void aEVD_actor_draw(ACTOR* actorx, GAME* game);
ACTOR_PROFILE Ev_Dokutu_Profile = {
mAc_PROFILE_EV_DOKUTU,
ACTOR_PART_NPC,
0,
SP_NPC_EV_DOKUTU,
ACTOR_OBJ_BANK_KEEP,
sizeof(EVENT_DOKUTU_ACTOR),
&aEVD_actor_ct,
&aEVD_actor_dt,
&aEVD_actor_init,
mActor_NONE_PROC1,
&aEVD_actor_save
};
static aNPC_ct_data_c ct_data = {
&aEVD_actor_move,
&aEVD_actor_draw,
3,
&aEVD_talk_request,
&aEVD_talk_init,
&aEVD_talk_end_chk,
0
};
static void aEVD_actor_ct(ACTOR* actorx, GAME* game) {
if ((*Common_Get(clip).npc_clip->birth_check_proc)(actorx, game) == TRUE) {
(*Common_Get(clip).npc_clip->ct_proc)(actorx, game, &ct_data);
}
}
static void aEVD_actor_save(ACTOR* actorx, GAME* game) {
mNpc_RenewalSetNpc(actorx);
}
static void aEVD_actor_dt(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->dt_proc)(actorx, game);
}
static void aEVD_actor_init(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->init_proc)(actorx, game);
}
static void aEVD_actor_move(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->move_proc)(actorx, game);
}
static void aEVD_actor_draw(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->draw_proc)(actorx, game);
}
@@ -0,0 +1,23 @@
static void aEVD_set_talk_info(ACTOR* actorx) {
mDemo_Set_msg_num(0x3146);
}
static void aEVD_talk_request(ACTOR* actorx, GAME* game) {
mDemo_Request(mDemo_TYPE_TALK, actorx, &aEVD_set_talk_info);
}
static int aEVD_talk_init(ACTOR* actorx, GAME* game) {
mDemo_Set_ListenAble();
return TRUE;
}
static int aEVD_talk_end_chk(ACTOR* actorx, GAME* game) {
int res = FALSE;
if (mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE) {
res = TRUE;
}
return res;
}
+306
View File
@@ -0,0 +1,306 @@
#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/actor/ac_ev_ghost_talk.c_inc"
#include "../src/actor/ac_ev_ghost_schedule.c_inc"
@@ -0,0 +1,305 @@
static void aEGH_look_player(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
if (ghost->npc_class.action.step == aNPC_ACTION_END_STEP) {
u8 action = 4;
s16 player_y = ghost->npc_class.actor_class.player_angle_y;
s16 rot_y = ghost->npc_class.actor_class.shape_info.rotation.y;
s16 diff = player_y - rot_y;
if (ABS(diff) < DEG2SHORT_ANGLE(67.5f)) {
action = 0;
}
aEGH_set_request_act(ghost, 4, action, 2, 1, 0, 0);
}
}
static int aEGH_bitset_func(u16 bit) {
u32 player_no = Common_Get(player_no);
mEv_gst_c* ghost_save = (mEv_gst_c*)mEv_get_save_area(mEv_EVENT_GHOST, 54);
mEv_gst_common_c* ghost_common = (mEv_gst_common_c*)mEv_get_common_area(mEv_EVENT_GHOST, 55);
if (player_no == mPr_FOREIGNER) {
if (ghost_common != NULL) {
ghost_common->flags |= bit;
return TRUE;
}
} else if (ghost_save != NULL) {
ghost_save->flags |= (u16)(bit << player_no);
return TRUE;
}
return FALSE;
}
static int aEGH_bitclr_func(u16 bit) {
u32 player_no = Common_Get(player_no);
mEv_gst_c* ghost_save = (mEv_gst_c*)mEv_get_save_area(mEv_EVENT_GHOST, 54);
mEv_gst_common_c* ghost_common = (mEv_gst_common_c*)mEv_get_common_area(mEv_EVENT_GHOST, 55);
if (player_no == mPr_FOREIGNER) {
if (ghost_common != NULL) {
ghost_common->flags &= ~bit;
return TRUE;
}
} else if (ghost_save != NULL) {
ghost_save->flags &= ~(u16)(bit << player_no);
return TRUE;
}
return FALSE;
}
static u16 aEGH_bitcheck_func(u16 bit) {
u32 player_no = Common_Get(player_no);
mEv_gst_c* ghost_save = (mEv_gst_c*)mEv_get_save_area(mEv_EVENT_GHOST, 54);
mEv_gst_common_c* ghost_common = (mEv_gst_common_c*)mEv_get_common_area(mEv_EVENT_GHOST, 55);
if (player_no == mPr_FOREIGNER) {
if (ghost_common != NULL) {
return ghost_common->flags & bit;
}
} else if (ghost_save != NULL) {
return (u16)(bit << player_no) & ghost_save->flags;
}
return FALSE;
}
static int aEGH_equal_block(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
int bx;
int bz;
mFI_Wpos2BlockNum(&bx, &bz, GET_PLAYER_ACTOR(play)->actor_class.world.position);
return bx == ghost->npc_class.actor_class.block_x && bz == ghost->npc_class.actor_class.block_z;
}
static int aEGH_time_over() {
return Common_Get(time.now_sec) > (4 * mTM_SECONDS_IN_HOUR);
}
static void aEGH_byebye_check(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
ACTOR* actorx = (ACTOR*)ghost;
if (mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE && mDemo_Check(mDemo_TYPE_SPEAK, actorx) == FALSE &&
aEGH_time_over() != FALSE) {
if (aEGH_equal_block(ghost, play)) {
switch (ghost->think_act) {
case aEGH_THINK_SPEAK: {
aEGH_setup_think_proc(ghost, play, aEGH_THINK_BYEBYE);
ghost->msg_no = 0x2EDD;
ghost->npc_class.actor_class.talk_distance = 1000.0f;
ghost->_9AA = 1;
break;
}
case aEGH_THINK_NORMAL_WAIT:
case aEGH_THINK_IRAI_AF:
case aEGH_THINK_BYE:
case aEGH_THINK_WELCOM: {
Actor_delete((ACTOR*)ghost);
break;
}
}
} else {
aEGH_setup_think_proc(ghost, play, aEGH_THINK_IRAI);
}
}
}
static void aEGH_irai(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
if (ghost->npc_class.actor_class.player_distance_xz > 220.0f) {
aEGH_setup_think_proc(ghost, play, aEGH_THINK_BYE);
}
}
static void aEGH_bye(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
if (ghost->npc_class.actor_class.player_distance_xz < 200.0f) {
aEGH_setup_think_proc(ghost, play, aEGH_THINK_WELCOM);
}
}
static void aEGH_byebye(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
if (ghost->alpha == 0) {
Actor_delete((ACTOR*)ghost);
} else {
if (ghost->bye_bye_timer != 0) {
ghost->bye_bye_timer--;
if (ghost->bye_bye_timer == 0) {
sAdo_SysTrgStart(0x16C);
}
} else {
if (ghost->bye_bye_angle < 30000) {
ghost->bye_bye_angle += 60;
}
ghost->npc_class.actor_class.shape_info.rotation.y += ghost->bye_bye_angle;
ghost->npc_class.actor_class.world.angle.y = ghost->npc_class.actor_class.shape_info.rotation.y;
ghost->npc_class.movement.mv_angl = ghost->npc_class.actor_class.world.angle.y;
ghost->npc_class.movement.mv_add_angl = 0;
}
if (ghost->bye_bye_scale_timer != 0) {
ghost->bye_bye_scale_timer--;
} else {
ghost->npc_class.actor_class.scale.x += -0.00004f;
ghost->npc_class.actor_class.scale.z = ghost->npc_class.actor_class.scale.x;
}
}
}
static void aEGH_speak_byebye(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
ACTOR* actorx = (ACTOR*)ghost;
if (mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE && mDemo_Check(mDemo_TYPE_SPEAK, actorx) == FALSE &&
aEGH_equal_block(ghost, play) == FALSE) {
aEGH_setup_think_proc(ghost, play, aEGH_THINK_IRAI);
}
}
static void aEGH_think_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play) {
EV_GHOST_ACTOR* ghost = (EV_GHOST_ACTOR*)actorx;
(*ghost->think_proc)(ghost, play);
aEGH_look_player(ghost, play);
}
static void aEGH_think_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play) {
EV_GHOST_ACTOR* ghost = (EV_GHOST_ACTOR*)actorx;
u8 think_act;
if (ghost->_9AC) {
ghost->_9AC = FALSE;
} else {
if (aEGH_bitcheck_func(aEGH_BIT_FOUND_GHOST)) {
ghost->alpha = 140;
think_act = aEGH_THINK_SPEAK;
} else {
ghost->alpha = 0;
think_act = aEGH_THINK_IRAI_AF;
}
actorx->actor_class.status_data.weight = 255;
actorx->condition_info.hide_request = FALSE;
aEGH_setup_think_proc(ghost, play, think_act);
actorx->condition_info.demo_flg = aNPC_COND_DEMO_SKIP_FOOTSTEPS_VFX | aNPC_COND_DEMO_SKIP_FEEL_CHECK |
aNPC_COND_DEMO_SKIP_FOOTSTEPS | aNPC_COND_DEMO_SKIP_ENTRANCE_CHECK |
aNPC_COND_DEMO_SKIP_HEAD_LOOKAT;
}
}
static void aEGH_normal_wait_init(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
(*Common_Get(clip).npc_clip->animation_init_proc)((ACTOR*)ghost, aNPC_ANIM_GSTWAIT1, FALSE);
ghost->npc_class.draw.main_animation.keyframe.frame_control.mode = cKF_FRAMECONTROL_REPEAT;
ghost->npc_class.action.idx = 0;
aEGH_set_request_act(ghost, 4, 0, 0, 0, 0, 0);
}
static void aEGH_irai_init(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
ghost->npc_class.actor_class.talk_distance = 80.0f;
aEGH_normal_wait_init(ghost, play);
ghost->msg_no = 0x2EE2;
}
static void aEGH_irai_af_init(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
ghost->npc_class.actor_class.talk_distance = 55.0f;
ghost->msg_no = 0x2EE7;
(*Common_Get(clip).npc_clip->chg_schedule_proc)((NPC_ACTOR*)ghost, play, 5);
ghost->npc_class.actor_class.status_data.weight = 80;
}
static void aEGH_bye_init(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
ghost->npc_class.actor_class.talk_distance = 280.0f;
aEGH_normal_wait_init(ghost, play);
ghost->msg_no = 0x2ED8;
}
static void aEGH_welcom_init(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
ghost->npc_class.actor_class.talk_distance = 200.0f;
aEGH_normal_wait_init(ghost, play);
ghost->msg_no = 0x2ED3;
}
static void aEGH_byebye_init(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
aEGH_bitclr_func(aEGH_BIT_FOUND_GHOST);
ghost->bye_bye_angle = -1000;
ghost->bye_bye_timer = 25;
ghost->bye_bye_scale_timer = 48;
ghost->bye_bye_transparency_delay_timer = 43;
aEGH_normal_wait_init(ghost, play);
ghost->npc_class.head.lock_flag = TRUE;
}
static aEGH_setup_c dt_tbl[aEGH_THINK_NUM] = {
{ aEGH_THINK_PROC_BYE, aEGH_THINK_INIT_NORMAL_WAIT, aEGH_TALK_REQUEST_NONE, aEGH_TALK_END_WAIT,
aEGH_THINK_NORMAL_WAIT },
{ aEGH_THINK_PROC_BYEBYE, aEGH_THINK_INIT_BYEBYE, aEGH_TALK_REQUEST_NONE, aEGH_TALK_END_WAIT, aEGH_THINK_IRAI },
{ aEGH_THINK_PROC_NONE, aEGH_THINK_INIT_WELCOM, aEGH_TALK_REQUEST_FORCE, aEGH_TALK_END_WAIT, aEGH_THINK_WELCOM },
{ aEGH_THINK_PROC_BYE, aEGH_THINK_INIT_BYE, aEGH_TALK_REQUEST_FORCE, aEGH_TALK_GIVE_ME_WAIT,
aEGH_THINK_NORMAL_WAIT },
{ aEGH_THINK_PROC_IRAI, aEGH_THINK_INIT_IRAI, aEGH_TALK_REQUEST_FORCE, aEGH_TALK_SELECT_WAIT, aEGH_THINK_SPEAK },
{ aEGH_THINK_PROC_SPEAK_BYEBYE, aEGH_THINK_INIT_NORMAL_WAIT, aEGH_TALK_REQUEST_FORCE, aEGH_TALK_SELECT_ROOF,
aEGH_THINK_IRAI },
{ aEGH_THINK_PROC_NONE, aEGH_THINK_INIT_IRAI_AF, aEGH_TALK_REQUEST_NORM, aEGH_TALK_END_WAIT, aEGH_THINK_SPEAK }
};
static aEGH_PROC proc_table[aEGH_THINK_PROC_NUM] = { (aEGH_PROC)&none_proc1, &aEGH_irai, &aEGH_bye, &aEGH_byebye,
&aEGH_speak_byebye };
static aEGH_PROC init_table[aEGH_THINK_INIT_NUM] = { (aEGH_PROC)&none_proc1, &aEGH_normal_wait_init, &aEGH_irai_init,
&aEGH_irai_af_init, &aEGH_bye_init, &aEGH_welcom_init,
&aEGH_byebye_init };
static void aEGH_setup_think_proc(EV_GHOST_ACTOR* ghost, GAME_PLAY* play, u8 think_act) {
static aNPC_TALK_REQUEST_PROC talk_request_table[aEGH_TALK_REQUEST_NUM] = { (aNPC_TALK_REQUEST_PROC)&none_proc1,
&aEGH_norm_talk_request,
&aEGH_force_talk_request };
aEGH_setup_c* data = &dt_tbl[think_act];
ghost->think_act = think_act;
ghost->think_proc = proc_table[data->think_proc];
ghost->npc_class.talk_info.talk_request_proc = talk_request_table[data->talk_request_proc];
ghost->talk_act = data->talk_act;
ghost->after_talk_think_act = data->talk_after_act;
(*init_table[data->think_init_proc])(ghost, play);
ghost->_9A7 = TRUE;
}
static void aEGH_think_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int think_type) {
switch (think_type) {
case 0:
aEGH_think_init_proc(actorx, play);
break;
case 1:
aEGH_think_main_proc(actorx, play);
break;
}
}
static void aEGH_schedule_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play) {
actorx->think.think_proc = &aEGH_think_proc;
(*Common_Get(clip).npc_clip->think_proc)(actorx, play, aNPC_THINK_SPECIAL, 0);
}
static void aEGH_schedule_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play) {
if ((*Common_Get(clip).npc_clip->think_proc)(actorx, play, -1, 1) == FALSE) {
(*Common_Get(clip).npc_clip->think_proc)(actorx, play, -1, 2);
}
}
static void aEGH_schedule_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int sched_type) {
switch (sched_type) {
case 0:
aEGH_schedule_init_proc(actorx, play);
break;
case 1:
aEGH_schedule_main_proc(actorx, play);
break;
}
}
+625
View File
@@ -0,0 +1,625 @@
static int aEGH_hitodama_num() {
int i;
int num;
Private_c* priv = Common_Get(now_private);
for (i = 0, num = 0; i < mEv_GHOST_HITODAMA_NUM; i++) {
int n = mPr_GetPossessionItemSumWithCond(priv, ITM_SPIRIT0 + i, mPr_ITEM_COND_NORMAL);
num += n * (i + 1);
}
return num;
}
static void aEGH_okoruhito() {
static u8 pf_string[mMsg_FREE_STRING_LEN];
mEv_gst_c* ghost_ev = (mEv_gst_c*)mEv_get_save_area(mEv_EVENT_GHOST, 54);
mString_Load_StringFromRom(pf_string, sizeof(pf_string), 0x62E + ghost_ev->okoruhito_str_no);
mMsg_Set_item_str(mMsg_Get_base_window_p(), mMsg_FREE_STR1, pf_string, sizeof(pf_string));
}
static void aEGH_delete_hitodama() {
int i;
int num;
Private_c* priv = Common_Get(now_private);
for (i = 0, num = 0; i < mEv_GHOST_HITODAMA_NUM; i++) {
int idx = mPr_GetPossessionItemIdxWithCond(priv, ITM_SPIRIT0 + i, mPr_ITEM_COND_NORMAL);
while (idx != -1) {
mPr_SetPossessionItem(Common_Get(now_private), idx, EMPTY_NO, mPr_ITEM_COND_NORMAL);
idx = mPr_GetPossessionItemIdxWithCond(priv, ITM_SPIRIT0 + i, mPr_ITEM_COND_NORMAL);
}
}
}
static mActor_name_t aEGH_get_collect(int selected_idx, mActor_name_t* list) {
while (*list != EMPTY_NO) {
if (mSP_CollectCheck(*list) == FALSE) {
if (selected_idx > 0) {
selected_idx--;
}
else {
return *list;
}
}
list++;
}
return EMPTY_NO;
}
static void aEGH_check_collect_num(int* list_num, int* uncollect_num, mActor_name_t* list) {
*list_num = 0;
*uncollect_num = 0;
while (*list != EMPTY_NO) {
(*list_num)++;
if (mSP_CollectCheck(*list) == FALSE) {
(*uncollect_num)++;
}
list++;
}
}
extern mActor_name_t ftr_listA[];
extern mActor_name_t ftr_listB[];
extern mActor_name_t ftr_listC[];
extern mActor_name_t ftr_listEvent[];
extern mActor_name_t ftr_listLottery[];
extern mActor_name_t carpet_listA[];
extern mActor_name_t carpet_listB[];
extern mActor_name_t carpet_listC[];
extern mActor_name_t carpet_listEvent[];
extern mActor_name_t wall_listA[];
extern mActor_name_t wall_listB[];
extern mActor_name_t wall_listC[];
extern mActor_name_t wall_listEvent[];
extern mActor_name_t cloth_listA[];
extern mActor_name_t cloth_listB[];
extern mActor_name_t cloth_listC[];
extern mActor_name_t cloth_listEvent[];
extern mActor_name_t binsen_listA[];
extern mActor_name_t binsen_listB[];
extern mActor_name_t binsen_listC[];
static mActor_name_t list_haniwa[HANIWA_NUM + 1] = {
FTR_HANIWA000_SOUTH,
FTR_HANIWA001_SOUTH,
FTR_HANIWA002_SOUTH,
FTR_HANIWA003_SOUTH,
FTR_HANIWA004_SOUTH,
FTR_HANIWA005_SOUTH,
FTR_HANIWA006_SOUTH,
FTR_HANIWA007_SOUTH,
FTR_HANIWA008_SOUTH,
FTR_HANIWA009_SOUTH,
FTR_HANIWA010_SOUTH,
FTR_HANIWA011_SOUTH,
FTR_HANIWA012_SOUTH,
FTR_HANIWA013_SOUTH,
FTR_HANIWA014_SOUTH,
FTR_HANIWA015_SOUTH,
FTR_HANIWA016_SOUTH,
FTR_HANIWA017_SOUTH,
FTR_HANIWA018_SOUTH,
FTR_HANIWA019_SOUTH,
FTR_HANIWA020_SOUTH,
FTR_HANIWA021_SOUTH,
FTR_HANIWA022_SOUTH,
FTR_HANIWA023_SOUTH,
FTR_HANIWA024_SOUTH,
FTR_HANIWA025_SOUTH,
FTR_HANIWA026_SOUTH,
FTR_HANIWA027_SOUTH,
FTR_HANIWA028_SOUTH,
FTR_HANIWA029_SOUTH,
FTR_HANIWA030_SOUTH,
FTR_HANIWA031_SOUTH,
FTR_HANIWA032_SOUTH,
FTR_HANIWA033_SOUTH,
FTR_HANIWA034_SOUTH,
FTR_HANIWA035_SOUTH,
FTR_HANIWA036_SOUTH,
FTR_HANIWA037_SOUTH,
FTR_HANIWA038_SOUTH,
FTR_HANIWA039_SOUTH,
FTR_HANIWA040_SOUTH,
FTR_HANIWA041_SOUTH,
FTR_HANIWA042_SOUTH,
FTR_HANIWA043_SOUTH,
FTR_HANIWA044_SOUTH,
FTR_HANIWA045_SOUTH,
FTR_HANIWA046_SOUTH,
FTR_HANIWA047_SOUTH,
FTR_HANIWA048_SOUTH,
FTR_HANIWA049_SOUTH,
FTR_HANIWA050_SOUTH,
FTR_HANIWA051_SOUTH,
FTR_HANIWA052_SOUTH,
FTR_HANIWA053_SOUTH,
FTR_HANIWA054_SOUTH,
FTR_HANIWA055_SOUTH,
FTR_HANIWA056_SOUTH,
FTR_HANIWA057_SOUTH,
FTR_HANIWA058_SOUTH,
FTR_HANIWA059_SOUTH,
FTR_HANIWA060_SOUTH,
FTR_HANIWA061_SOUTH,
FTR_HANIWA062_SOUTH,
FTR_HANIWA063_SOUTH,
FTR_HANIWA064_SOUTH,
FTR_HANIWA065_SOUTH,
FTR_HANIWA066_SOUTH,
FTR_HANIWA067_SOUTH,
FTR_HANIWA068_SOUTH,
FTR_HANIWA069_SOUTH,
FTR_HANIWA070_SOUTH,
FTR_HANIWA071_SOUTH,
FTR_HANIWA072_SOUTH,
FTR_HANIWA073_SOUTH,
FTR_HANIWA074_SOUTH,
FTR_HANIWA075_SOUTH,
FTR_HANIWA076_SOUTH,
FTR_HANIWA077_SOUTH,
FTR_HANIWA078_SOUTH,
FTR_HANIWA079_SOUTH,
FTR_HANIWA080_SOUTH,
FTR_HANIWA081_SOUTH,
FTR_HANIWA082_SOUTH,
FTR_HANIWA083_SOUTH,
FTR_HANIWA084_SOUTH,
FTR_HANIWA085_SOUTH,
FTR_HANIWA086_SOUTH,
FTR_HANIWA087_SOUTH,
FTR_HANIWA088_SOUTH,
FTR_HANIWA089_SOUTH,
FTR_HANIWA090_SOUTH,
FTR_HANIWA091_SOUTH,
FTR_HANIWA092_SOUTH,
FTR_HANIWA093_SOUTH,
FTR_HANIWA094_SOUTH,
FTR_HANIWA095_SOUTH,
FTR_HANIWA096_SOUTH,
FTR_HANIWA097_SOUTH,
FTR_HANIWA098_SOUTH,
FTR_HANIWA099_SOUTH,
FTR_HANIWA100_SOUTH,
FTR_HANIWA101_SOUTH,
FTR_HANIWA102_SOUTH,
FTR_HANIWA103_SOUTH,
FTR_HANIWA104_SOUTH,
FTR_HANIWA105_SOUTH,
FTR_HANIWA106_SOUTH,
FTR_HANIWA107_SOUTH,
FTR_HANIWA108_SOUTH,
FTR_HANIWA109_SOUTH,
FTR_HANIWA110_SOUTH,
FTR_HANIWA111_SOUTH,
FTR_HANIWA112_SOUTH,
FTR_HANIWA113_SOUTH,
FTR_HANIWA114_SOUTH,
FTR_HANIWA115_SOUTH,
FTR_HANIWA116_SOUTH,
FTR_HANIWA117_SOUTH,
FTR_HANIWA118_SOUTH,
FTR_HANIWA119_SOUTH,
FTR_HANIWA120_SOUTH,
FTR_HANIWA121_SOUTH,
FTR_HANIWA122_SOUTH,
FTR_HANIWA123_SOUTH,
FTR_HANIWA124_SOUTH,
FTR_HANIWA125_SOUTH,
FTR_HANIWA126_SOUTH,
EMPTY_NO /* end of list */
};
static mActor_name_t umbrella_list[UMBRELLA_NUM + 1] = {
ITM_UMBRELLA00,
ITM_UMBRELLA01,
ITM_UMBRELLA02,
ITM_UMBRELLA03,
ITM_UMBRELLA04,
ITM_UMBRELLA05,
ITM_UMBRELLA06,
ITM_UMBRELLA07,
ITM_UMBRELLA08,
ITM_UMBRELLA09,
ITM_UMBRELLA10,
ITM_UMBRELLA11,
ITM_UMBRELLA12,
ITM_UMBRELLA13,
ITM_UMBRELLA14,
ITM_UMBRELLA15,
ITM_UMBRELLA16,
ITM_UMBRELLA17,
ITM_UMBRELLA18,
ITM_UMBRELLA19,
ITM_UMBRELLA20,
ITM_UMBRELLA21,
ITM_UMBRELLA22,
ITM_UMBRELLA23,
ITM_UMBRELLA24,
ITM_UMBRELLA25,
ITM_UMBRELLA26,
ITM_UMBRELLA27,
ITM_UMBRELLA28,
ITM_UMBRELLA29,
ITM_UMBRELLA30,
ITM_UMBRELLA31,
EMPTY_NO /* end of list */
};
static mActor_name_t aEGH_not_collect_get() {
static mActor_name_t* item_list[aEGH_ITEM_LIST_NUM] = {
ftr_listA,
ftr_listB,
ftr_listC,
ftr_listEvent,
ftr_listLottery,
carpet_listA,
carpet_listB,
carpet_listC,
carpet_listEvent,
wall_listA,
wall_listB,
wall_listC,
wall_listEvent,
cloth_listA,
cloth_listB,
cloth_listC,
cloth_listEvent,
binsen_listA,
binsen_listB,
binsen_listC,
list_haniwa,
umbrella_list
};
int list_num_tbl[aEGH_ITEM_LIST_NUM];
int uncollect_num_tbl[aEGH_ITEM_LIST_NUM];
int no_uncollected_flag = FALSE;
int selected_idx;
mActor_name_t item;
int i;
int total_count;
/* Calculate total items in each list and uncollected items in each list */
for (i = 0; i < aEGH_ITEM_LIST_NUM; i++) {
aEGH_check_collect_num(&list_num_tbl[i], &uncollect_num_tbl[i], item_list[i]);
}
for (i = 0, total_count = 0; i < aEGH_ITEM_LIST_NUM; i++) {
total_count += uncollect_num_tbl[i];
}
/* If no uncollected items remain, select one at random from all lists */
if (total_count == 0) {
no_uncollected_flag = TRUE; /* all items collected */
for (i = 0, total_count = 0; i < aEGH_ITEM_LIST_NUM; i++) {
total_count += list_num_tbl[i];
}
}
selected_idx = RANDOM(total_count);
if (no_uncollected_flag) {
/* Transform the absolute idx into the list idx by removing all entries up to the selected list */
for (i = 0; i < aEGH_ITEM_LIST_NUM && selected_idx >= list_num_tbl[i]; i++) {
selected_idx -= list_num_tbl[i];
}
if (i != aEGH_ITEM_LIST_NUM) {
item = item_list[i][selected_idx];
}
else {
item = ITM_FOOD_PEACH; /* If we somehow failed to select an item, we'll give them a peach */
}
}
else {
/* Transform the absolute idx into the list idx by removing all entries up to the selected list */
for (i = 0; i < aEGH_ITEM_LIST_NUM && selected_idx >= uncollect_num_tbl[i]; i++) {
selected_idx -= uncollect_num_tbl[i];
}
if (i != aEGH_ITEM_LIST_NUM) {
item = aEGH_get_collect(selected_idx, item_list[i]); /* Get the uncollected item from the list */
if (item == EMPTY_NO) {
item = ITM_FOOD_APPLE; /* If we somehow failed to get an uncollected item, we'll give them an apple */
}
}
else {
item = ITM_FOOD_PEACH; /* If we somehow failed to select an item, we'll give them a peach */
}
}
return mRmTp_FtrItemNo2Item1ItemNo(item, TRUE);
}
static void aEGH_give_me_wait(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
switch (order) {
case 1:
{
mPlib_request_main_give_type1((GAME*)play, ITM_SPIRIT0, 7, FALSE, FALSE);
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 2);
mMsg_Set_LockContinue(mMsg_Get_base_window_p());
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 1, 3);
aEGH_delete_hitodama();
break;
}
case 2:
{
if (Common_Get(clip).handOverItem_clip->master_actor == NULL) {
mMsg_Unset_LockContinue(mMsg_Get_base_window_p());
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
aEGH_change_talk_proc(ghost, aEGH_TALK_SELECT_WAIT);
}
break;
}
}
}
static void aEGH_select_wait(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
mMsg_Window_c* msg_p = mMsg_Get_base_window_p();
mEv_gst_c* ghost_data = (mEv_gst_c*)mEv_get_save_area(mEv_EVENT_GHOST, 54);
if (order == 1 && mMsg_Check_MainNormalContinue(mMsg_Get_base_window_p())) {
ghost->after_talk_think_act = 1;
ghost_data->flags |= mEv_GHOST_FLAG_RETURNED_SPIRITS;
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
switch (mChoice_Get_ChoseNum(mChoice_Get_base_window_p())) {
case mChoice_CHOICE0: /* Clear weeds */
{
u32 num_weeds = mFI_GetItemNumField(GRASS_A, GRASS_C);
if (num_weeds < 50) {
mMsg_Set_continue_msg_num(msg_p, 0x2EF1);
}
else if (num_weeds < 150) {
mMsg_Set_continue_msg_num(msg_p, 0x2EF2);
}
else if (num_weeds < 450) {
mMsg_Set_continue_msg_num(msg_p, 0x2EF3);
}
else if (num_weeds < 900) {
mMsg_Set_continue_msg_num(msg_p, 0x2EF4);
}
else {
mMsg_Set_continue_msg_num(msg_p, 0x2EF5);
}
aEGH_change_talk_proc(ghost, aEGH_TALK_CLEAR_GRASS);
break;
}
case mChoice_CHOICE1:
{
aEGH_change_talk_proc(ghost, aEGH_TALK_SELECT_ROOF);
ghost->roof_pal = 0;
break;
}
case mChoice_CHOICE2:
{
u8 name[mIN_ITEM_NAME_LEN];
aEGH_change_talk_proc(ghost, aEGH_TALK_GIVE_YOU_WAIT);
ghost->give_item = aEGH_not_collect_get();
mIN_copy_name_str(name, ghost->give_item);
mMsg_Set_item_str_art(msg_p, mMsg_ITEM_STR0, name, mIN_ITEM_NAME_LEN, mIN_get_item_article(ghost->give_item));
break;
}
}
}
}
static void aEGH_select_roof(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
int arrange_idx = mHS_get_arrange_idx(Common_Get(player_no));
mHm_hs_c* home = Save_GetPointer(homes[arrange_idx]);
if (order == 1 && mMsg_Check_MainNormalContinue(mMsg_Get_base_window_p())) {
int selected;
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
selected = mChoice_Get_ChoseNum(mChoice_Get_base_window_p());
if (selected >= mChoice_CHOICE3) {
ghost->roof_pal += 3;
if (ghost->roof_pal >= mSP_ROOF_COLOR_NUM) {
ghost->roof_pal = 0;
}
}
else {
ghost->roof_pal += (u8)selected;
home->outlook_pal = ghost->roof_pal;
/* Only update the 'next outlook' palette if the player doesn't have a coat of paint already scheduled */
if ((Common_Get(now_private)->state_flags & mPr_FLAG_UPDATE_OUTLOOK_PENDING) == 0) {
home->next_outlook_pal = ghost->roof_pal;
}
aEGH_change_talk_proc(ghost, aEGH_TALK_END_WAIT);
}
}
}
static void aEGH_give_you_wait(EV_GHOST_ACTOR* ghost, GAME_PLAY* play) {
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 1);
if (order == 2) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 0, ghost->give_item);
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 1, 7);
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 2, 0);
mPr_SetFreePossessionItem(Common_Get(now_private), ghost->give_item, mPr_ITEM_COND_NORMAL);
aEGH_change_talk_proc(ghost, aEGH_TALK_END_WAIT);
}
}
static int aEGH_change_talk_proc(EV_GHOST_ACTOR* ghost, u8 talk_act) {
ghost->talk_act = talk_act;
return TRUE;
}
static void aEGH_set_force_talk_info(ACTOR* actorx) {
EV_GHOST_ACTOR* ghost = (EV_GHOST_ACTOR*)actorx;
mEv_gst_common_c* ghost_common = (mEv_gst_common_c*)mEv_get_common_area(mEv_EVENT_GHOST, 55);
mDemo_Set_msg_num(ghost->msg_no + RANDOM(5));
aEGH_okoruhito();
switch (ghost->msg_no) {
case 0x2EE2:
{
mDemo_Set_talk_turn(TRUE);
mDemo_Set_camera(CAMERA2_PROCESS_TALK);
if (aEGH_bitcheck_func(aEGH_BIT_FOUND_GHOST) == FALSE) {
sAdo_SysTrgStart(0x6B);
aEGH_bitset_func(aEGH_BIT_FOUND_GHOST);
}
ghost_common->flags |= mEv_GHOST_FLAG_ACTIVE;
break;
}
case 0x2EDD:
{
mDemo_Set_talk_turn(TRUE);
mDemo_Set_camera(CAMERA2_PROCESS_NORMAL);
break;
}
case 0x2ED3:
case 0x2ED8:
{
mDemo_Set_talk_turn(FALSE);
mDemo_Set_camera(CAMERA2_PROCESS_NORMAL);
mMsg_sound_set_voice_click(mMsg_Get_base_window_p());
break;
}
default:
{
mDemo_Set_talk_turn(FALSE);
mDemo_Set_camera(CAMERA2_PROCESS_NORMAL);
break;
}
}
aEGH_change_talk_proc(ghost, aEGH_TALK_END_WAIT);
}
static void aEGH_force_talk_request(ACTOR* actorx, GAME* game) {
EV_GHOST_ACTOR* ghost = (EV_GHOST_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
f32 dist = GET_PLAYER_ACTOR(play)->actor_class.world.position.y - actorx->world.position.y;
if (dist < 0.0f) {
dist = -dist;
}
if (!(
!(ghost->_9A7 == FALSE && actorx->player_distance_xz < actorx->talk_distance) ||
!(dist < 60.0f) && (ghost->_9AA == FALSE)
)) {
mDemo_Request(mDemo_TYPE_SPEAK, actorx, &aEGH_set_force_talk_info);
}
else {
ghost->_9A7 = FALSE;
}
}
static void aEGH_set_norm_talk_info(ACTOR* actorx) {
EV_GHOST_ACTOR* ghost = (EV_GHOST_ACTOR*)actorx;
int hitodama_num;
int msg_no;
aEGH_okoruhito();
mDemo_Set_talk_turn(TRUE);
mDemo_Set_camera(CAMERA2_PROCESS_TALK);
aEGH_change_talk_proc(ghost, aEGH_TALK_END_WAIT);
hitodama_num = aEGH_hitodama_num();
if (hitodama_num == 0) {
msg_no = 0x2EE7 + RANDOM(5);
}
else if (hitodama_num >= mEv_GHOST_HITODAMA_NUM) {
msg_no = 0x2EF0;
aEGH_change_talk_proc(ghost, aEGH_TALK_GIVE_ME_WAIT);
Save_Get(event_save_common).ghost_day = 0;
}
else {
msg_no = 0x2EEB + hitodama_num;
}
mDemo_Set_msg_num(msg_no);
}
static void aEGH_norm_talk_request(ACTOR* actorx, GAME* game) {
EV_GHOST_ACTOR* ghost = (EV_GHOST_ACTOR*)actorx;
if (ghost->_9A7 == FALSE) {
mDemo_Request(mDemo_TYPE_TALK, actorx, &aEGH_set_norm_talk_info);
}
else {
ghost->_9A7 = FALSE;
}
}
static int aEGH_talk_init(ACTOR* actorx, GAME* game) {
EV_GHOST_ACTOR* ghost = (EV_GHOST_ACTOR*)actorx;
ghost->npc_class.talk_info.talk_request_proc = (aNPC_TALK_REQUEST_PROC)&none_proc1;
mDemo_Set_ListenAble();
mDemo_Start(actorx);
return TRUE;
}
typedef void (*aEGH_TALK_PROC)(EV_GHOST_ACTOR*, GAME_PLAY*);
static int aEGH_talk_end_chk(ACTOR* actorx, GAME* game) {
static aEGH_TALK_PROC proc[aEGH_TALK_NUM] = {
(aEGH_TALK_PROC)&none_proc1,
&aEGH_give_me_wait,
&aEGH_select_wait,
&aEGH_select_roof,
&aEGH_give_you_wait,
(aEGH_TALK_PROC)&none_proc1
};
EV_GHOST_ACTOR* ghost = (EV_GHOST_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
int res = FALSE;
(*proc[ghost->talk_act])(ghost, play);
if (mDemo_Check(mDemo_TYPE_SPEAK, actorx) == FALSE && mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE) {
if (ghost->talk_act == aEGH_TALK_CLEAR_GRASS) {
Save_Set(clear_grass, TRUE);
}
aEGH_setup_think_proc(ghost, play, ghost->after_talk_think_act);
if (ghost->melody_inst != 0) {
ghost->npc_class.talk_info.melody_inst = ghost->melody_inst;
ghost->melody_inst = 0;
}
res = TRUE;
}
return res;
}
+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/actor/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;
}
}
+84
View File
@@ -0,0 +1,84 @@
#include "ac_ev_kabuPeddler.h"
#include "m_common_data.h"
#include "m_font.h"
#include "m_msg.h"
#include "m_player_lib.h"
#include "m_play.h"
enum {
aEKPD_ACTION_TALK_END_WAIT,
aEKPD_ACTION_SELL_CHECK,
aEKPD_ACTION_SELL_CHECK_AFTER,
aEKPD_ACTION_SELL_CHECK2,
aEKPD_ACTION_SELL_CEHCK_AFTER2,
aEKPD_ACTION_MONEY_GET_DEMO_START_WAIT,
aEKPD_ACTION_MONEY_GET_DEMO_END_WAIT,
aEKPD_ACTION_KABU_TRANS_DEMO_START_WAIT,
aEKPD_ACTION_NUM
};
static void aEKPD_actor_ct(ACTOR* actorx, GAME* game);
static void aEKPD_actor_dt(ACTOR* actorx, GAME* game);
static void aEKPD_actor_draw(ACTOR* actorx, GAME* game);
static void aEKPD_actor_move(ACTOR* actorx, GAME* game);
static void aEKPD_actor_save(ACTOR* actorx, GAME* game);
static void aEKPD_actor_init(ACTOR* actorx, GAME* game);
ACTOR_PROFILE Ev_KabuPeddler_Profile = {
mAc_PROFILE_EV_KABUPEDDLER,
ACTOR_PART_NPC,
ACTOR_STATE_NONE,
SP_NPC_KABUPEDDLER,
ACTOR_OBJ_BANK_KEEP,
sizeof(EV_KABUPEDDLER_ACTOR),
&aEKPD_actor_ct,
&aEKPD_actor_dt,
&aEKPD_actor_init,
mActor_NONE_PROC1,
&aEKPD_actor_save
};
static void aEKPD_setupAction(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play, int talk_act);
static void aEKPD_talk_request(ACTOR*, GAME*);
static int aEKPD_talk_init(ACTOR*, GAME*);
static int aEKPD_talk_end_chk(ACTOR*, GAME*);
static void aEKPD_actor_ct(ACTOR* actorx, GAME* game) {
static aNPC_ct_data_c ct_data = {
&aEKPD_actor_move,
&aEKPD_actor_draw,
3,
&aEKPD_talk_request,
&aEKPD_talk_init,
&aEKPD_talk_end_chk,
0
};
EV_KABUPEDDLER_ACTOR* kabuPeddler = (EV_KABUPEDDLER_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);
kabuPeddler->setup_talk_proc = &aEKPD_setupAction;
}
}
static void aEKPD_actor_save(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->save_proc)(actorx, game);
}
static void aEKPD_actor_dt(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->dt_proc)(actorx, game);
mEv_actor_dying_message(mEv_EVENT_KABU_PEDDLER, actorx);
}
static void aEKPD_actor_init(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->init_proc)(actorx, game);
}
static void aEKPD_actor_draw(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->draw_proc)(actorx, game);
}
#include "../src/actor/ac_ev_kabuPeddler_move.c_inc"
@@ -0,0 +1,219 @@
static int aEKPD_check_look() {
mEv_kabu_peddler_c* peddler_data = &Save_Get(event_save_data).weekly.kabu_peddler;
int res = FALSE;
if (mPr_CheckCmpPersonalID(&peddler_data->spoken_pids[Common_Get(player_no)],
&Common_Get(now_private)->player_ID) == TRUE) {
res = TRUE;
}
return res;
}
static void aEKPD_set_price_str_sub(u32 price, int free_str_no) {
u8 price_str[6];
mFont_UnintToString(price_str, sizeof(price_str), price, 5, TRUE, FALSE, TRUE);
mMsg_Set_free_str(mMsg_Get_base_window_p(), free_str_no, price_str, sizeof(price_str));
}
static void aEKPD_set_price_str() {
static int sum[aEKPD_KABU_TYPE_NUM] = { 1, 10, 50, 100 };
u32 price = Save_Get(kabu_price_schedule).daily_price[lbRTC_SUNDAY];
int i;
for (i = 0; i < aEKPD_KABU_TYPE_NUM; i++) {
aEKPD_set_price_str_sub(price * sum[i], i);
}
}
static int aEKPD_get_trans_space_idx() {
return mPr_GetPossessionItemIdx(Common_Get(now_private), EMPTY_NO);
}
static void aEKPD_hand_over_kabu(int idx, int kabu_type) {
static mActor_name_t kabu_no[aEKPD_KABU_TYPE_NUM - 1] = { ITM_KABU_10, ITM_KABU_50, ITM_KABU_100 };
mPr_SetPossessionItem(Common_Get(now_private), idx, kabu_no[kabu_type], mPr_ITEM_COND_NORMAL);
}
static void aEKPD_sell_check(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) {
static int next_act[] = { aEKPD_ACTION_TALK_END_WAIT, aEKPD_ACTION_SELL_CHECK_AFTER, aEKPD_ACTION_SELL_CEHCK_AFTER2,
0 };
int talk_act_idx;
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
if (order != 0 && mMsg_Check_MainNormalContinue(mMsg_Get_base_window_p()) == TRUE) {
int choseNum = mChoice_Get_ChoseNum(mChoice_Get_base_window_p());
switch (choseNum) {
case mChoice_CHOICE0:
case mChoice_CHOICE1:
case mChoice_CHOICE2: {
if (kabuPeddler->talk_act == aEKPD_ACTION_SELL_CHECK) {
talk_act_idx = 1;
} else {
talk_act_idx = 2;
}
break;
}
case mChoice_CHOICE3: {
talk_act_idx = 3;
break;
}
default: {
talk_act_idx = 0;
break;
}
}
if (talk_act_idx != 0) {
(*kabuPeddler->setup_talk_proc)(kabuPeddler, play, next_act[talk_act_idx]);
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
kabuPeddler->kabu_type = choseNum;
}
}
}
static void aEKPD_sell_check_after(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) {
static int sell_sum[aEKPD_KABU_TYPE_NUM] = { 10, 50, 100, 0 };
static int next_msg_no[] = { 0x0711, 0x0710, 0x070F };
static int next_msg_no2[] = { 0x0711, 0x0717, 0x0716 };
static int next_act[] = { aEKPD_ACTION_MONEY_GET_DEMO_START_WAIT, aEKPD_ACTION_TALK_END_WAIT,
aEKPD_ACTION_TALK_END_WAIT };
if (mMsg_Check_MainNormalContinue(mMsg_Get_base_window_p()) == TRUE) {
u32 price;
int talk_act_idx;
int trans_space_idx = aEKPD_get_trans_space_idx();
if (trans_space_idx != -1) {
price = Save_Get(kabu_price_schedule).daily_price[lbRTC_SUNDAY] * sell_sum[kabuPeddler->kabu_type];
if (mSP_money_check(price) == TRUE) {
mSP_get_sell_price(price); /* take money from player */
aEKPD_hand_over_kabu(trans_space_idx, kabuPeddler->kabu_type);
talk_act_idx = 0;
} else {
talk_act_idx = 1;
}
} else {
talk_act_idx = 2;
}
if (kabuPeddler->talk_act == 2) {
mMsg_Set_continue_msg_num(mMsg_Get_base_window_p(), next_msg_no[talk_act_idx]);
} else {
mMsg_Set_continue_msg_num(mMsg_Get_base_window_p(), next_msg_no2[talk_act_idx]);
}
(*kabuPeddler->setup_talk_proc)(kabuPeddler, play, next_act[talk_act_idx]);
}
}
static void aEKPD_money_get_demo_start_wait(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) {
if (Common_Get(clip).handOverItem_clip->request_mode == aHOI_REQUEST_TRANS_WAIT) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 1, 3);
(*kabuPeddler->setup_talk_proc)(kabuPeddler, play, aEKPD_ACTION_MONEY_GET_DEMO_END_WAIT);
}
}
static void aEKPD_money_get_demo_end_wait(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) {
if (Common_Get(clip).handOverItem_clip->master_actor == NULL) {
mMsg_Unset_LockContinue(mMsg_Get_base_window_p());
(*kabuPeddler->setup_talk_proc)(kabuPeddler, play, aEKPD_ACTION_KABU_TRANS_DEMO_START_WAIT);
}
}
static void aEKPD_kabu_trans_demo_start_wait(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) {
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 1);
if (order == 2) {
(*kabuPeddler->setup_talk_proc)(kabuPeddler, play, aEKPD_ACTION_SELL_CHECK2);
}
}
static void aEKPD_sell_check_init(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) {
aEKPD_set_price_str();
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
static void aEKPD_sell_check2_init(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 0, (mActor_name_t)(ITM_KABU_START + kabuPeddler->kabu_type));
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 1, 7);
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 2, 0);
}
static void aEKPD_money_get_demo_start_wait_init(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) {
mMsg_Set_LockContinue(mMsg_Get_base_window_p());
mPlib_request_main_give_type1((GAME*)play, ITM_MONEY_10000, 7, FALSE, FALSE);
}
typedef void (*aEKPD_INIT_PROC)(EV_KABUPEDDLER_ACTOR*, GAME_PLAY*);
static void aEKPD_init_proc(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play, int act) {
static aEKPD_INIT_PROC init_proc[aEKPD_ACTION_NUM] = {
(aEKPD_INIT_PROC)&none_proc1, &aEKPD_sell_check_init, (aEKPD_INIT_PROC)&none_proc1,
&aEKPD_sell_check2_init, (aEKPD_INIT_PROC)&none_proc1, &aEKPD_money_get_demo_start_wait_init,
(aEKPD_INIT_PROC)&none_proc1, (aEKPD_INIT_PROC)&none_proc1
};
(*init_proc[act])(kabuPeddler, play);
}
static void aEKPD_setupAction(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play, int act) {
static aEKPD_PROC process[aEKPD_ACTION_NUM] = { (aEKPD_PROC)&none_proc1, &aEKPD_sell_check,
&aEKPD_sell_check_after, &aEKPD_sell_check,
&aEKPD_sell_check_after, &aEKPD_money_get_demo_start_wait,
&aEKPD_money_get_demo_end_wait, &aEKPD_kabu_trans_demo_start_wait };
kabuPeddler->talk_act = act;
kabuPeddler->talk_proc = process[act];
aEKPD_init_proc(kabuPeddler, play, act);
}
static void aEKPD_set_talk_info(ACTOR* actorx) {
int msg_no = aEKPD_check_look() == TRUE ? 0x0718 : 0x06FD;
mDemo_Set_msg_num(msg_no);
}
static void aEKPD_talk_request(ACTOR* actorx, GAME* game) {
mDemo_Request(mDemo_TYPE_TALK, actorx, &aEKPD_set_talk_info);
}
static int aEKPD_talk_init(ACTOR* actorx, GAME* game) {
EV_KABUPEDDLER_ACTOR* kabuPeddler = (EV_KABUPEDDLER_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
if (aEKPD_check_look() == FALSE) {
mEv_kabu_peddler_c* kabu_data = &Save_Get(event_save_data).weekly.kabu_peddler;
mPr_CopyPersonalID(&kabu_data->spoken_pids[Common_Get(player_no)], &Common_Get(now_private)->player_ID);
}
(*kabuPeddler->setup_talk_proc)(kabuPeddler, play, aEKPD_ACTION_SELL_CHECK);
mDemo_Set_ListenAble();
return TRUE;
}
static int aEKPD_talk_end_chk(ACTOR* actorx, GAME* game) {
EV_KABUPEDDLER_ACTOR* kabuPeddler = (EV_KABUPEDDLER_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
int res = FALSE;
(*kabuPeddler->talk_proc)(kabuPeddler, play);
if (mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE) {
mEv_set_status(mEv_EVENT_KABU_PEDDLER, mEv_STATUS_TALK);
res = TRUE;
}
return res;
}
static void aEKPD_actor_move(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->move_proc)(actorx, game);
}
+73
View File
@@ -0,0 +1,73 @@
#include "ac_ev_majin.h"
#include "m_common_data.h"
#include "m_name_table.h"
#include "m_demo.h"
extern void aEMJ_actor_ct(ACTOR*, GAME*);
extern void aEMJ_actor_dt(ACTOR*, GAME*);
extern void aEMJ_actor_init(ACTOR*, GAME*);
extern void aEMJ_actor_save(ACTOR*, GAME*);
ACTOR_PROFILE Ev_Majin_Profile = {
mAc_PROFILE_EV_MAJIN, ACTOR_PART_NPC, ACTOR_STATE_NO_DRAW_WHILE_CULLED | ACTOR_STATE_NO_MOVE_WHILE_CULLED,
SP_NPC_EV_MAJIN, ACTOR_OBJ_BANK_KEEP, sizeof(EV_NPCMAJIN_ACTOR),
aEMJ_actor_ct, aEMJ_actor_dt, aEMJ_actor_init,
NONE_ACTOR_PROC, aEMJ_actor_save,
};
extern void aEMJ_actor_move(ACTOR*, GAME*);
extern void aEMJ_actor_draw(ACTOR*, GAME*);
static int aEMJ_talk_init(ACTOR*, GAME*);
static int aEMJ_talk_end_chk(ACTOR*, GAME*);
static void aEMJ_schedule_proc(NPC_ACTOR*, GAME_PLAY*, int);
void aEMJ_actor_ct(ACTOR* actor, GAME* game) {
static aNPC_ct_data_c ct_data = {
&aEMJ_actor_move, &aEMJ_actor_draw, 5, mActor_NONE_PROC1, &aEMJ_talk_init, &aEMJ_talk_end_chk, 0,
};
EV_NPCMAJIN_ACTOR* majin = (EV_NPCMAJIN_ACTOR*)actor;
if (Common_Get(clip.npc_clip)->birth_check_proc(actor, game) == TRUE) {
majin->npc_class.schedule.schedule_proc = aEMJ_schedule_proc;
Common_Get(clip.npc_clip)->ct_proc(actor, game, &ct_data);
majin->npc_class.head.lock_flag = 1;
majin->npc_class.talk_info.default_turn_animation = aNPC_ANIM_WAIT_R1;
majin->npc_class.talk_info.default_animation = aNPC_ANIM_WAIT_R1;
majin->npc_class.talk_info.turn = 2;
}
}
void aEMJ_actor_save(ACTOR* actor, GAME* game) {
Common_Get(clip.npc_clip)->save_proc(actor, game);
}
void aEMJ_actor_dt(ACTOR* actor, GAME* game) {
if (Common_Get(clip.groundhog_control_clip) != NULL) {
Common_Get(clip.groundhog_control_clip)->groundhog_npc_actor = NULL;
}
Common_Get(clip.npc_clip)->dt_proc(actor, game);
Common_Get(clip.effect_clip)->effect_kill_proc(eEC_EFFECT_RESET_HOLE, RSV_NO);
}
void aEMJ_actor_init(ACTOR* actor, GAME* game) {
Common_Get(clip.npc_clip)->init_proc(actor, game);
}
void aEMJ_set_animation(ACTOR* actor, int idx) {
static s16 animeSeqNo[] = { aNPC_ANIM_APPEAR1, aNPC_ANIM_WAIT_R1, aNPC_ANIM_GO_UG1 };
Common_Get(clip.npc_clip)->animation_init_proc(actor, animeSeqNo[idx], 0);
}
void aEMJ_actor_move(ACTOR* actor, GAME* game) {
Common_Get(clip.npc_clip)->move_proc(actor, game);
actor->shape_info.draw_shadow = 0;
}
void aEMJ_actor_draw(ACTOR* actor, GAME* game) {
Common_Get(clip.npc_clip)->draw_proc(actor, game);
}
#include "../src/actor/ac_ev_majin_move.c_inc"
+157
View File
@@ -0,0 +1,157 @@
void aEMJ_schedule_proc(NPC_ACTOR*, GAME_PLAY*, int);
void aEMJ_setup_think_proc(NPC_ACTOR*, int);
void aEMJ_force_talk_request(NPC_ACTOR*, GAME_PLAY*);
void aEMJ_set_request_act(NPC_ACTOR* actor, GAME_PLAY* play) {
EV_NPCMAJIN_ACTOR* majin = (EV_NPCMAJIN_ACTOR*)actor;
majin->npc_class.request.act_priority = 4;
majin->npc_class.request.act_idx = 22;
majin->npc_class.request.act_type = 2;
}
void aEMJ_act_init_proc(NPC_ACTOR* actor, GAME_PLAY* play) {
EV_NPCMAJIN_ACTOR* majin = (EV_NPCMAJIN_ACTOR*)actor;
majin->npc_class.action.step = 0;
}
void aEMJ_act_proc(NPC_ACTOR* actor, GAME_PLAY* play, int idx) {
static aNPC_SUB_PROC act_proc[] = { aEMJ_act_init_proc, (aNPC_SUB_PROC)mActor_NONE_PROC1,
(aNPC_SUB_PROC)mActor_NONE_PROC1 };
act_proc[idx](actor, play);
}
void aEMJ_appear(NPC_ACTOR* actor, GAME_PLAY* play) {
EV_NPCMAJIN_ACTOR* majin = (EV_NPCMAJIN_ACTOR*)actor;
if (majin->npc_class.draw.main_animation_state == cKF_STATE_STOPPED) {
aEMJ_setup_think_proc(actor, 1);
}
}
void aEMJ_retire(NPC_ACTOR* actor, GAME_PLAY* play) {
if (actor->draw.main_animation_state == cKF_STATE_STOPPED) {
((NPC_ACTOR*)(actor->actor_class.parent_actor))->npc_info.animal = (Animal_c*)1;
Actor_delete(&actor->actor_class);
}
}
void aEMJ_think_main_proc(NPC_ACTOR* actor, GAME_PLAY* play) {
EV_NPCMAJIN_ACTOR* majin = (EV_NPCMAJIN_ACTOR*)actor;
if (actor->action.idx == 0x16) {
majin->think_proc(actor, play);
} else {
if (actor->action.step == aNPC_ACTION_END_STEP) {
aEMJ_set_request_act(actor, play);
}
}
}
void aEMJ_think_init_proc(ACTOR* actor, GAME* game) {
EV_NPCMAJIN_ACTOR* majin = (EV_NPCMAJIN_ACTOR*)actor;
GAME_PLAY* play = (GAME_PLAY*)game;
majin->npc_class.action.act_proc = aEMJ_act_proc;
aEMJ_set_request_act(&majin->npc_class, play);
Common_Get(clip).effect_clip->effect_make_proc(0x5D, actor->world.position, 3, actor->shape_info.rotation.y,
&play->game, 0xFFFF, 0, 0);
aEMJ_setup_think_proc(&majin->npc_class, 0);
}
void aEMJ_setup_think_proc(NPC_ACTOR* actor, int idx) {
static NPC_DT_PROCS dt_tbl[] = {
{ aEMJ_appear, (aNPC_SUB_PROC)none_proc1 },
{ (aNPC_SUB_PROC)none_proc1, aEMJ_force_talk_request },
{ aEMJ_retire, (aNPC_SUB_PROC)none_proc1 },
};
EV_NPCMAJIN_ACTOR* majin = (EV_NPCMAJIN_ACTOR*)actor;
NPC_DT_PROCS* current = &dt_tbl[idx];
majin->unk994 = idx;
majin->think_proc = current->unk0;
actor->talk_info.talk_request_proc = (mActor_proc)current->unk4;
aEMJ_set_animation(&actor->actor_class, idx);
}
void aEMJ_think_proc(NPC_ACTOR* actor, GAME_PLAY* play, int idx) {
static aNPC_SUB_PROC think_proc[] = {
(aNPC_SUB_PROC)(aEMJ_think_init_proc),
aEMJ_think_main_proc,
};
think_proc[idx](actor, play);
}
void aEMJ_schedule_init_proc(NPC_ACTOR* actor, GAME_PLAY* play) {
EV_NPCMAJIN_ACTOR* majin = (EV_NPCMAJIN_ACTOR*)actor;
majin->npc_class.think.think_proc = aEMJ_think_proc;
majin->npc_class.condition_info.hide_request = 0;
majin->npc_class.palActorIgnoreTimer = -1;
majin->npc_class.actor_class.world.position.x += 20.0f;
majin->npc_class.actor_class.world.position.z += 20.0f;
Common_Get(clip.npc_clip)->think_proc(actor, play, 9, 0);
}
void aEMJ_schedule_main_proc(NPC_ACTOR* actor, GAME_PLAY* play) {
EV_NPCMAJIN_ACTOR* majin = (EV_NPCMAJIN_ACTOR*)actor;
if (Common_Get(clip.npc_clip)->think_proc(actor, play, -1, 1) == 0) {
Common_Get(clip.npc_clip)->think_proc(actor, play, -1, 2);
}
}
void aEMJ_schedule_proc(NPC_ACTOR* actor, GAME_PLAY* play, int idx) {
static aNPC_SUB_PROC sche_proc[] = { aEMJ_schedule_init_proc, aEMJ_schedule_main_proc };
sche_proc[idx](actor, play);
}
void aEMJ_set_force_talk_info() {
int msg_num;
switch (Common_Get(weather)) {
case mEnv_WEATHER_CLEAR:
msg_num = RANDOM(3.0f) + 0x3DAF;
break;
case mEnv_WEATHER_SNOW:
msg_num = RANDOM(3.0f) + 0x3DB2;
break;
default:
case mEnv_WEATHER_RAIN:
msg_num = 0x3DAF;
break;
}
mDemo_Set_msg_num(msg_num);
}
void aEMJ_force_talk_request(NPC_ACTOR* actor, GAME_PLAY* play) {
mDemo_Request(10, &actor->actor_class, aEMJ_set_force_talk_info);
}
int aEMJ_talk_init(ACTOR* actor, GAME* play) {
EV_NPCMAJIN_ACTOR* majin = (EV_NPCMAJIN_ACTOR*)actor;
majin->npc_class.talk_info.talk_request_proc = (mActor_proc)none_proc1;
mDemo_Set_ListenAble();
return 1;
}
int aEMJ_talk_end_chk(ACTOR* actor, GAME* play) {
EV_NPCMAJIN_ACTOR* majin = (EV_NPCMAJIN_ACTOR*)actor;
int res = 0;
if (mDemo_Check(10, actor) == 0) {
aEMJ_setup_think_proc(&majin->npc_class, 2);
res = 1;
}
return res;
}
+140
View File
@@ -0,0 +1,140 @@
#include "ac_ev_santa.h"
#include "libultra/libultra.h"
#include "m_common_data.h"
#include "m_msg.h"
#include "m_play.h"
enum {
aESNT_ACTION_TALK_END_WAIT,
aESNT_ACTION_CHK_WISH_1ST,
aESNT_ACTION_CHK_WISH_2ND,
aESNT_ACTION_CHK_WISH_FINAL,
aESNT_ACTION_CHK_WISH_MORE,
aESNT_ACTION_MOTION_START_WAIT,
aESNT_ACTION_MOTION_END_WAIT,
aESNT_ACTION_NUM
};
enum {
aESNT_WISH_FTR,
aESNT_WISH_CLOTH,
aESNT_WISH_WALL,
aESNT_WISH_CARPET,
aESNT_WISH_NUM
};
#define aESNT_TALK_TALK_SAME_PLAYER_NUM 3
#define aESNT_TALK_TALK_OTHER_PLAYER_NUM 3
#define aESNT_TALK_FINAL_PRESENT_NUM 1
#define aESNT_TALK_FINAL_NO_PRESENT_NUM 1
#define aESNT_TALK_SAME_BLOCK_NUM 3
#define aESNT_TALK_HELLO_NUM 1
#define aESNT_TALK_CHK_1ST_NUM 1
#define aESNT_TALK_CHK_2ND_NUM 1
#define aESNT_TALK_CHK_FINAL_NUM aESNT_WISH_NUM
#define aESNT_TALK_ALMOST_RECOGNIZE_NUM 1
#define aESNT_TALK_FINAL_PRESENT2_NUM 1
#define aESNT_TALK_FINAL_NO_PRESENT2_NUM 1
#define aESNT_TALK_NO_MORE_PRESENTS_NUM 3
enum {
aESNT_TALK_TALK_SAME_PLAYER,
aESNT_TALK_TALK_OTHER_PLAYER = aESNT_TALK_TALK_SAME_PLAYER + aESNT_TALK_TALK_SAME_PLAYER_NUM,
aESNT_TALK_FINAL_PRESENT = aESNT_TALK_TALK_OTHER_PLAYER + aESNT_TALK_TALK_OTHER_PLAYER_NUM,
aESNT_TALK_FINAL_NO_PRESENT = aESNT_TALK_FINAL_PRESENT + aESNT_TALK_FINAL_PRESENT_NUM,
aESNT_TALK_SAME_BLOCK = aESNT_TALK_FINAL_NO_PRESENT + aESNT_TALK_FINAL_NO_PRESENT_NUM,
aESNT_TALK_HELLO = aESNT_TALK_SAME_BLOCK + aESNT_TALK_SAME_BLOCK_NUM,
aESNT_TALK_CHK_1ST = aESNT_TALK_HELLO + aESNT_TALK_HELLO_NUM,
aESNT_TALK_CHK_2ND = aESNT_TALK_CHK_1ST + aESNT_TALK_CHK_1ST_NUM,
aESNT_TALK_CHK_FINAL = aESNT_TALK_CHK_2ND + aESNT_TALK_CHK_2ND_NUM,
aESNT_TALK_ALMOST_RECOGNIZE = aESNT_TALK_CHK_FINAL + aESNT_TALK_CHK_FINAL_NUM,
aESNT_TALK_FINAL_PRESENT2 = aESNT_TALK_ALMOST_RECOGNIZE + aESNT_TALK_ALMOST_RECOGNIZE_NUM,
aESNT_TALK_FINAL_NO_PRESENT2 = aESNT_TALK_FINAL_PRESENT2 + aESNT_TALK_FINAL_PRESENT2_NUM,
aESNT_TALK_NO_MORE_PRESENTS = aESNT_TALK_FINAL_NO_PRESENT2 + aESNT_TALK_FINAL_NO_PRESENT2_NUM,
aESNT_TALK_NUM = aESNT_TALK_NO_MORE_PRESENTS + aESNT_TALK_NO_MORE_PRESENTS_NUM
};
static void aESNT_actor_ct(ACTOR*, GAME*);
static void aESNT_actor_dt(ACTOR*, GAME*);
static void aESNT_actor_init(ACTOR*, GAME*);
static void aESNT_actor_move(ACTOR*, GAME*);
static void aESNT_actor_draw(ACTOR*, GAME*);
static void aESNT_actor_save(ACTOR*, GAME*);
static void aESNT_talk_request(ACTOR*, GAME*);
static int aESNT_talk_init(ACTOR*, GAME*);
static int aESNT_talk_end_chk(ACTOR*, GAME*);
static void aESNT_setupAction(EVENT_SANTA_ACTOR*, GAME_PLAY*, int);
ACTOR_PROFILE Ev_Santa_Profile = {
mAc_PROFILE_EV_SANTA,
ACTOR_PART_NPC,
ACTOR_STATE_NONE,
SP_NPC_SANTA,
ACTOR_OBJ_BANK_KEEP,
sizeof(EVENT_SANTA_ACTOR),
&aESNT_actor_ct,
&aESNT_actor_dt,
&aESNT_actor_init,
mActor_NONE_PROC1,
&aESNT_actor_save
};
static void aESNT_actor_ct(ACTOR* actorx, GAME* game) {
static aNPC_ct_data_c ct_data = {
&aESNT_actor_move,
&aESNT_actor_draw,
3,
&aESNT_talk_request,
&aESNT_talk_init,
&aESNT_talk_end_chk,
0
};
EVENT_SANTA_ACTOR* santa = (EVENT_SANTA_ACTOR*)actorx;
if ((*Common_Get(clip).npc_clip->birth_check_proc)(actorx, game) == TRUE) {
mEv_santa_event_c* event_p;
mEv_santa_event_common_c* event_common_p;
(*Common_Get(clip).npc_clip->ct_proc)(actorx, game, &ct_data);
santa->setup_talk_proc = &aESNT_setupAction;
event_p = (mEv_santa_event_c*)mEv_get_save_area(mEv_EVENT_TOY_DAY_JINGLE, 0);
if (event_p == NULL) {
/* Reserve event data */
event_p = (mEv_santa_event_c*)mEv_reserve_save_area(mEv_EVENT_TOY_DAY_JINGLE, 0);
bzero(event_p, sizeof(mEv_santa_event_c));
mPr_ClearPersonalID(&event_p->pid);
}
santa->event_p = event_p;
event_common_p = (mEv_santa_event_common_c*)mEv_get_common_area(mEv_EVENT_TOY_DAY_JINGLE, 0);
if (event_common_p == NULL) {
event_common_p = (mEv_santa_event_common_c*)mEv_reserve_common_area(mEv_EVENT_TOY_DAY_JINGLE, 0);
}
santa->event_common_p = event_common_p;
}
}
static void aESNT_actor_save(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->save_proc)(actorx, game);
}
static void aESNT_actor_dt(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->dt_proc)(actorx, game);
mEv_actor_dying_message(mEv_EVENT_TOY_DAY_JINGLE, actorx);
}
static void aESNT_actor_init(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->init_proc)(actorx, game);
}
static void aESNT_actor_draw(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->draw_proc)(actorx, game);
}
#include "../src/actor/ac_ev_santa_move.c_inc"
+365
View File
@@ -0,0 +1,365 @@
static void aESNT_chk_wish_1st(EVENT_SANTA_ACTOR* santa, GAME_PLAY* play) {
if (mMsg_Check_MainNormalContinue(mMsg_Get_base_window_p()) == TRUE) {
mEv_santa_event_common_c* event_common_p = santa->event_common_p;
int present_flag;
switch (mChoice_Get_ChoseNum(mChoice_Get_base_window_p())) {
case mChoice_CHOICE0:
present_flag = 0;
break;
default:
present_flag = 1;
break;
}
if (santa->talk_act != aESNT_ACTION_CHK_WISH_1ST) {
present_flag <<= 1;
}
event_common_p->present |= present_flag;
(*santa->setup_talk_proc)(santa, play, aESNT_ACTION_TALK_END_WAIT);
}
}
static void aESNT_chk_wish_final(EVENT_SANTA_ACTOR* santa, GAME_PLAY* play) {
if (mMsg_Check_MainNormalContinue(mMsg_Get_base_window_p()) == TRUE) {
mEv_santa_event_common_c* event_common_p = santa->event_common_p;
int present_flag = event_common_p->present;
switch (mChoice_Get_ChoseNum(mChoice_Get_base_window_p())) {
case mChoice_CHOICE0:
present_flag &= 1; /* Furniture & Cloth */
break;
default:
present_flag &= 2; /* Wallpaper & Carpet */
if ((present_flag & aESNT_WISH_WALL) == 0) {
present_flag = aESNT_WISH_CARPET;
}
break;
}
event_common_p->present = present_flag;
(*santa->setup_talk_proc)(santa, play, aESNT_ACTION_TALK_END_WAIT);
}
}
static void aESNT_chk_wish_more(EVENT_SANTA_ACTOR* santa, GAME_PLAY* play) {
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9);
if (order != 0) {
mEv_santa_event_common_c* event_common_p = santa->event_common_p;
u8 present = aESNT_WISH_FTR;
switch (mMsg_Get_msg_num(mMsg_Get_base_window_p())) {
case MSG_SANTA_WISH_FTR:
present = aESNT_WISH_FTR;
break;
case MSG_SANTA_WISH_WALL:
present = aESNT_WISH_WALL;
break;
case MSG_SANTA_WISH_CARPET:
present = aESNT_WISH_CARPET;
break;
case MSG_SANTA_WISH_CLOTH:
present = aESNT_WISH_CLOTH;
break;
}
event_common_p->present = present;
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
(*santa->setup_talk_proc)(santa, play, aESNT_ACTION_TALK_END_WAIT);
}
}
static void aESNT_motion_start_wait(EVENT_SANTA_ACTOR* santa, GAME_PLAY* play) {
int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 1);
if (order == 2) {
(*santa->setup_talk_proc)(santa, play, aESNT_ACTION_MOTION_END_WAIT);
}
}
typedef void (*aESNT_INIT_PROC)(EVENT_SANTA_ACTOR*, GAME_PLAY*);
static void aESNT_chk_wish_more_init(EVENT_SANTA_ACTOR* santa, GAME_PLAY* play) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
}
static void aESNT_motion_end_wait_init(EVENT_SANTA_ACTOR* santa, GAME_PLAY* play) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 0, ITM_PRESENT);
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 1, 7);
mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 2, 1);
}
static void aESNT_init_proc(EVENT_SANTA_ACTOR* santa, GAME_PLAY* play, int act) {
static aESNT_INIT_PROC init_proc[aESNT_ACTION_NUM] = {
(aESNT_INIT_PROC)&none_proc1,
(aESNT_INIT_PROC)&none_proc1,
(aESNT_INIT_PROC)&none_proc1,
(aESNT_INIT_PROC)&none_proc1,
&aESNT_chk_wish_more_init,
(aESNT_INIT_PROC)&none_proc1,
&aESNT_motion_end_wait_init
};
(*init_proc[act])(santa, play);
}
static void aESNT_setupAction(EVENT_SANTA_ACTOR* santa, GAME_PLAY* play, int act) {
static aESNT_TALK_PROC process[aESNT_ACTION_NUM] = {
(aESNT_TALK_PROC)&none_proc1,
&aESNT_chk_wish_1st,
&aESNT_chk_wish_1st,
&aESNT_chk_wish_final,
&aESNT_chk_wish_more,
&aESNT_motion_start_wait,
(aESNT_TALK_PROC)&none_proc1
};
santa->talk_act = act;
santa->talk_proc = process[act];
aESNT_init_proc(santa, play, act);
}
static int aESNT_check_pl_cloth(mEv_santa_event_c* event_p) {
mActor_name_t* cloth_p = event_p->cloth;
mActor_name_t pl_cloth = Common_Get(now_private)->cloth.item;
int i;
int res = TRUE;
for (i = 0; i != event_p->present_count; i++) {
if (*cloth_p == pl_cloth) {
res = FALSE;
break;
}
cloth_p++;
}
return res;
}
static int aESNT_before_talk_present_decide_talk_data_idx(EVENT_SANTA_ACTOR* santa, mEv_santa_event_c* event_p, mEv_santa_event_common_c* event_common_p, int type) {
static int talk_data_idx[2][2] = {
{ aESNT_TALK_FINAL_PRESENT, aESNT_TALK_FINAL_NO_PRESENT },
{ aESNT_TALK_FINAL_PRESENT2, aESNT_TALK_FINAL_NO_PRESENT2 }
};
static int category[aESNT_WISH_NUM] = { mSP_KIND_FURNITURE, mSP_KIND_CLOTH, mSP_KIND_WALLPAPER, mSP_KIND_CARPET };
int item_idx = mPr_GetPossessionItemIdx(Common_Get(now_private), EMPTY_NO);
int inv_full;
mActor_name_t present;
if (item_idx != -1) {
if (event_common_p->present >= aESNT_WISH_NUM) {
event_common_p->present = aESNT_WISH_CARPET;
}
mSP_SelectRandomItem_New(NULL, &present, 1, NULL, 0, category[event_common_p->present], mSP_LISTTYPE_CHRISTMAS, FALSE);
mPr_SetPossessionItem(Common_Get(now_private), item_idx, present, mPr_ITEM_COND_PRESENT);
mPr_CopyPersonalID(&event_p->pid, &Common_Get(now_private)->player_ID);
santa->present = present;
event_common_p->talk_counter = 0;
event_p->cloth[event_p->present_count] = Common_Get(now_private)->cloth.item;
event_p->present_count++;
inv_full = FALSE;
}
else {
inv_full = TRUE;
}
return talk_data_idx[type][inv_full];
}
static int aESNT_before_talk_more_check_decide_talk_data_idx(mEv_santa_event_common_c* event_common_p) {
int talk_data_idx = aESNT_TALK_HELLO;
switch (event_common_p->talk_counter) {
case 0:
talk_data_idx = aESNT_TALK_HELLO;
break;
case 1:
talk_data_idx = aESNT_TALK_CHK_1ST;
break;
case 2:
talk_data_idx = aESNT_TALK_CHK_2ND;
break;
case 3:
talk_data_idx = aESNT_TALK_CHK_FINAL + event_common_p->present; /* select index based on desired present */
break;
}
event_common_p->talk_counter++;
return talk_data_idx;
}
static int aESNT_before_talk_decide_talk_data_idx(EVENT_SANTA_ACTOR* santa, GAME_PLAY* play, mEv_santa_event_c* event_p, mEv_santa_event_common_c* event_common_p) {
int talk_data_idx;
/* @BUG - because we compare the acre the player is in (GAME_PLAY block table)
* against the last acre we talked to Jingle, we can actually talk to him again
* without having to find him again. If you trap him at the border of an acre
* and then move into the adjacent acre and talk to him, GAME_PLAY's block state
* updates which passes the 'same block' check. Rinse and repeat between two acres
* to satisfy the talk requirements without having to do the search portion.
*/
#if !defined(BUGFIXES) || defined(ALLOW_EXPLOITS)
if (play->block_table.block_x == event_common_p->bx && play->block_table.block_z == event_common_p->bz) {
talk_data_idx = aESNT_TALK_SAME_BLOCK + RANDOM(aESNT_TALK_SAME_BLOCK_NUM);
}
#else
/* Use Jingle's actor block instead of GAME_PLAY's current block (player block) */
if (santa->npc_class.actor_class.block_x == event_common_p->bx && santa->npc_class.actor_class.block_x == event_common_p->bz) {
talk_data_idx = aESNT_TALK_SAME_BLOCK + RANDOM(aESNT_TALK_SAME_BLOCK_NUM);
}
#endif
else if (event_common_p->talk_counter >= 4) {
talk_data_idx = aESNT_before_talk_present_decide_talk_data_idx(santa, event_p, event_common_p, 0);
}
else {
talk_data_idx = aESNT_before_talk_more_check_decide_talk_data_idx(event_common_p);
}
if (talk_data_idx != aESNT_TALK_FINAL_NO_PRESENT) {
/* Update talked acre */
#if !defined(BUGFIXES) || defined(ALLOW_EXPLOITS)
event_common_p->bx = play->block_table.block_x;
event_common_p->bz = play->block_table.block_z;
#else
event_common_p->bx = santa->npc_class.actor_class.block_x;
event_common_p->bz = santa->npc_class.actor_class.block_z;
#endif
}
return talk_data_idx;
}
static int aESNT_after_talk_restart_Q_decide_talk_data_idx(mEv_santa_event_common_c* event_common_p) {
event_common_p->last_talk_cloth = Common_Get(now_private)->cloth.item;
event_common_p->talk_counter++;
return aESNT_TALK_ALMOST_RECOGNIZE;
}
static int aESNT_after_talk_same_pl_decide_talk_data_idx(EVENT_SANTA_ACTOR* santa, mEv_santa_event_c* event_p, mEv_santa_event_common_c* event_common_p) {
int talk_data_idx;
if (aESNT_check_pl_cloth(event_p) == TRUE) {
if (event_p->present_count >= mEv_SANTA_CLOTH_NUM_MAX) {
talk_data_idx = aESNT_TALK_NO_MORE_PRESENTS + RANDOM(aESNT_TALK_NO_MORE_PRESENTS_NUM);
}
else if (event_common_p->talk_counter == 0) {
talk_data_idx = aESNT_after_talk_restart_Q_decide_talk_data_idx(event_common_p);
}
else if (event_common_p->last_talk_cloth == Common_Get(now_private)->cloth.item) {
talk_data_idx = aESNT_before_talk_present_decide_talk_data_idx(santa, event_p, event_common_p, 1);
}
else {
talk_data_idx = aESNT_after_talk_restart_Q_decide_talk_data_idx(event_common_p);
event_common_p->talk_counter = 1;
}
}
else {
event_common_p->talk_counter = 0;
talk_data_idx = aESNT_TALK_TALK_SAME_PLAYER + RANDOM(aESNT_TALK_TALK_SAME_PLAYER_NUM);
}
return talk_data_idx;
}
static int aESNT_after_talk_other_pl_decide_talk_data_idx(mEv_santa_event_c* event_p) {
mMsg_Set_free_str(mMsg_Get_base_window_p(), mMsg_FREE_STR0, event_p->pid.player_name, PLAYER_NAME_LEN);
return aESNT_TALK_TALK_OTHER_PLAYER + RANDOM(aESNT_TALK_TALK_OTHER_PLAYER_NUM);
}
static int aESNT_after_talk_decide_talk_data_idx(EVENT_SANTA_ACTOR* santa, mEv_santa_event_c* event_p, mEv_santa_event_common_c* event_common_p) {
if (mPr_CheckCmpPersonalID(&event_p->pid, &Common_Get(now_private)->player_ID) == TRUE) {
return aESNT_after_talk_same_pl_decide_talk_data_idx(santa, event_p, event_common_p);
}
else {
return aESNT_after_talk_other_pl_decide_talk_data_idx(event_p);
}
}
static void aESNT_getP_talk_data(ACTOR* actorx) {
static aESNT_talk_data_c talk_data[aESNT_TALK_NUM] = {
{ 0x07BF, aESNT_ACTION_TALK_END_WAIT },
{ 0x07C0, aESNT_ACTION_TALK_END_WAIT },
{ 0x07C1, aESNT_ACTION_TALK_END_WAIT },
{ 0x07C2, aESNT_ACTION_TALK_END_WAIT },
{ 0x07C3, aESNT_ACTION_TALK_END_WAIT },
{ 0x07C4, aESNT_ACTION_TALK_END_WAIT },
{ 0x07BA, aESNT_ACTION_MOTION_START_WAIT },
{ 0x07B9, aESNT_ACTION_TALK_END_WAIT },
{ 0x07BC, aESNT_ACTION_TALK_END_WAIT },
{ 0x07BD, aESNT_ACTION_TALK_END_WAIT },
{ 0x07BE, aESNT_ACTION_TALK_END_WAIT },
{ 0x07AA, aESNT_ACTION_TALK_END_WAIT },
{ 0x07AB, aESNT_ACTION_CHK_WISH_1ST },
{ 0x07AE, aESNT_ACTION_CHK_WISH_2ND },
{ 0x07B2, aESNT_ACTION_CHK_WISH_FINAL },
{ 0x07B4, aESNT_ACTION_CHK_WISH_FINAL },
{ 0x07B1, aESNT_ACTION_CHK_WISH_FINAL },
{ 0x07B3, aESNT_ACTION_CHK_WISH_FINAL },
{ 0x2B4C, aESNT_ACTION_CHK_WISH_MORE },
{ 0x2B59, aESNT_ACTION_MOTION_START_WAIT },
{ 0x2B58, aESNT_ACTION_TALK_END_WAIT },
{ 0x2B5B, aESNT_ACTION_TALK_END_WAIT },
{ 0x2B5C, aESNT_ACTION_TALK_END_WAIT },
{ 0x2B5D, aESNT_ACTION_TALK_END_WAIT }
};
EVENT_SANTA_ACTOR* santa = (EVENT_SANTA_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)gamePT;
mEv_santa_event_c* event_p = santa->event_p;
mEv_santa_event_common_c* event_common_p = santa->event_common_p;
int talk_data_idx;
if (mPr_NullCheckPersonalID(&event_p->pid) == FALSE) {
talk_data_idx = aESNT_after_talk_decide_talk_data_idx(santa, event_p, event_common_p);
}
else {
talk_data_idx = aESNT_before_talk_decide_talk_data_idx(santa, play, event_p, event_common_p);
}
santa->talk_data_p = &talk_data[talk_data_idx];
}
static void aESNT_set_talk_info(ACTOR* actorx) {
EVENT_SANTA_ACTOR* santa = (EVENT_SANTA_ACTOR*)actorx;
aESNT_getP_talk_data(actorx);
mEv_set_status(mEv_EVENT_TOY_DAY_JINGLE, mEv_STATUS_TALK);
mDemo_Set_msg_num(santa->talk_data_p->msg_no);
}
static void aESNT_talk_request(ACTOR* actorx, GAME* game) {
mDemo_Request(mDemo_TYPE_TALK, actorx, &aESNT_set_talk_info);
}
static int aESNT_talk_init(ACTOR* actorx, GAME* game) {
EVENT_SANTA_ACTOR* santa = (EVENT_SANTA_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
(*santa->setup_talk_proc)(santa, play, santa->talk_data_p->talk_act);
mDemo_Set_ListenAble();
return TRUE;
}
static int aESNT_talk_end_chk(ACTOR* actorx, GAME* game) {
EVENT_SANTA_ACTOR* santa = (EVENT_SANTA_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
int res = FALSE;
(*santa->talk_proc)(santa, play);
if (mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE) {
res = TRUE;
}
return res;
}
static void aESNT_actor_move(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->move_proc)(actorx, game);
}
+83
View File
@@ -0,0 +1,83 @@
#include "ac_ev_soncho.h"
#include "m_common_data.h"
typedef struct soncho_event_save_s {
u16 _00;
u8 msg_no;
} aESC_event_save_c;
static void aESC_actor_ct(ACTOR* actorx, GAME* game);
static void aESC_actor_dt(ACTOR* actorx, GAME* game);
static void aESC_actor_init(ACTOR* actorx, GAME* game);
static void aESC_actor_draw(ACTOR* actorx, GAME* game);
static void aESC_actor_save(ACTOR* actorx, GAME* game);
static void aESC_actor_move(ACTOR* actorx, GAME* game);
static void aESC_talk_request(ACTOR* actorx, GAME* game);
static int aESC_talk_init(ACTOR* actorx, GAME* game);
static int aESC_talk_end_chk(ACTOR* actorx, GAME* game);
ACTOR_PROFILE Ev_Soncho_Profile = {
mAc_PROFILE_EV_SONCHO,
ACTOR_PART_NPC,
0,
SP_NPC_EV_SONCHO,
ACTOR_OBJ_BANK_KEEP,
sizeof(EVENT_SONCHO_ACTOR),
&aESC_actor_ct,
&aESC_actor_dt,
&aESC_actor_init,
mActor_NONE_PROC1,
&aESC_actor_save
};
static aNPC_ct_data_c ct_data = {
&aESC_actor_move,
&aESC_actor_draw,
4,
&aESC_talk_request,
&aESC_talk_init,
&aESC_talk_end_chk,
1
};
static void aESC_actor_ct(ACTOR* actorx, GAME* game) {
EVENT_SONCHO_ACTOR* soncho_actor = (EVENT_SONCHO_ACTOR*)actorx;
aESC_event_save_c* soncho_event = (aESC_event_save_c*)mEv_get_save_area(mEv_EVENT_SONCHO_BRIDGE_MAKE, 34);
if ((*Common_Get(clip).npc_clip->birth_check_proc)(actorx, game) == TRUE) {
(*Common_Get(clip).npc_clip->ct_proc)(actorx, game, &ct_data);
soncho_actor->npc_class.palActorIgnoreTimer = -1;
soncho_actor->npc_class.draw._5BD = 3;
if (soncho_event == NULL) {
soncho_event = (aESC_event_save_c*)mEv_reserve_save_area(mEv_EVENT_SONCHO_BRIDGE_MAKE, 34);
soncho_event->_00 = 0;
soncho_event->msg_no = RANDOM(5);
}
if (Save_Get(bridge).pending) {
Actor_delete(actorx);
}
}
}
static void aESC_actor_save(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->save_proc)(actorx, game);
}
static void aESC_actor_dt(ACTOR* actorx, GAME* game) {
mEv_actor_dying_message(mEv_EVENT_SONCHO_BRIDGE_MAKE, actorx);
(*Common_Get(clip).npc_clip->dt_proc)(actorx, game);
}
static void aESC_actor_init(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->init_proc)(actorx, game);
}
static void aESC_actor_draw(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->draw_proc)(actorx, game);
}
#include "../src/actor/ac_ev_soncho_talk.c_inc"
+174
View File
@@ -0,0 +1,174 @@
#include "m_msg.h"
#include "m_font.h"
static int aESC_bitset_func() {
u8 flags = Common_Get(spnpc_first_talk_flags);
if (Common_Get(player_no) == mPr_FOREIGNER) {
return FALSE;
}
Common_Get(spnpc_first_talk_flags) = flags | (1 << aNPC_SPNPC_BIT_EV_SONCHO);
return TRUE;
}
static u16 aESC_bitcheck_func() {
u8 flags = Common_Get(spnpc_first_talk_flags);
if (Common_Get(player_no) == mPr_FOREIGNER) {
return FALSE;
}
return (Common_Get(spnpc_first_talk_flags) >> aNPC_SPNPC_BIT_EV_SONCHO) & 1;
}
static void aESC_owari_message() {
mMsg_Window_c* win_p = mMsg_Get_base_window_p();
aESC_event_save_c* ev_save = (aESC_event_save_c*)mEv_get_save_area(mEv_EVENT_SONCHO_BRIDGE_MAKE, 34);
if ((*(u8*)&Save_Get(event_save_common).bridge_flags) & 0x80) {
mMsg_Set_continue_msg_num(win_p, 0x2F47 + ev_save->msg_no);
}
else {
mMsg_Set_continue_msg_num(win_p, 0x2F39 + ev_save->msg_no);
}
ev_save->msg_no++;
if (ev_save->msg_no >= 5) {
ev_save->msg_no = 0;
}
}
static void aESC_set_day() {
u8 day_str[16];
int len = mFont_UnintToString(day_str, 16, Save_Get(bridge).build_date.day, 16, TRUE, FALSE, TRUE);
mMsg_Set_free_str(mMsg_Get_base_window_p(), mMsg_FREE_STR0, day_str, len);
}
/* They forgot to change the prefix on this copy-paste */
static int aEGH_change_talk_proc(EVENT_SONCHO_ACTOR* soncho, u8 state) {
soncho->talk_state = state;
return TRUE;
}
static void aESC_talk_select(EVENT_SONCHO_ACTOR* soncho, GAME* game) {
lbRTC_time_c rtc_time = Common_Get(time.rtc_time);
if ((int)mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9) == 1 && mMsg_Check_MainNormalContinue(mMsg_Get_base_window_p())) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
aEGH_change_talk_proc(soncho, aESC_TALK_OWARI);
switch (mChoice_Get_ChoseNum(mChoice_Get_base_window_p())) {
case 1:
{
Save_Get(bridge).pending = TRUE;
lbRTC_Add_DD(&rtc_time, 1);
Save_Get(bridge).build_date.year = rtc_time.year;
Save_Get(bridge).build_date.month = rtc_time.month;
Save_Get(bridge).build_date.day = rtc_time.day;
Save_Get(bridge).block_x = soncho->npc_class.actor_class.block_x;
Save_Get(bridge).block_z = soncho->npc_class.actor_class.block_z;
aESC_set_day();
break;
}
case 0:
{
if (soncho->first_talk != FALSE) {
aESC_owari_message();
}
else {
aEGH_change_talk_proc(soncho, aESC_TALK_SECAND);
}
break;
}
}
}
}
static void aESC_talk_secand(EVENT_SONCHO_ACTOR* soncho, GAME* game) {
if ((int)mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9) == 1 && mMsg_Check_MainNormalContinue(mMsg_Get_base_window_p())) {
mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0);
aEGH_change_talk_proc(soncho, aESC_TALK_OWARI);
aESC_owari_message();
}
}
static int aESC_time_talk() {
lbRTC_time_c rtc_time = Common_Get(time.rtc_time);
if (rtc_time.hour < 6 || rtc_time.hour >= 23) {
return 0x2F36;
}
else if (rtc_time.hour < 10) {
return 0x2F33;
}
else if (rtc_time.hour < 17) {
return 0x2F34;
}
else {
return 0x2F35;
}
}
static void aESC_set_talk_info_talk_request(ACTOR* actorx) {
int msg_no;
EVENT_SONCHO_ACTOR* soncho = (EVENT_SONCHO_ACTOR*)actorx;
aEGH_change_talk_proc(soncho, 0);
if (Save_Get(bridge).pending) {
msg_no = 0x2F44 + RANDOM(3);
aESC_set_day();
}
else if (aESC_bitcheck_func()) {
msg_no = 0x2F3E;
aEGH_change_talk_proc(soncho, aESC_TALK_SELECT);
soncho->first_talk = FALSE;
}
else {
msg_no = aESC_time_talk();
aEGH_change_talk_proc(soncho, aESC_TALK_SELECT);
soncho->first_talk = TRUE;
}
mDemo_Set_msg_num(msg_no);
}
static void aESC_talk_request(ACTOR* actorx, GAME* game) {
mDemo_Request(mDemo_TYPE_TALK, actorx, &aESC_set_talk_info_talk_request);
}
static int aESC_talk_init(ACTOR* actorx, GAME* game) {
aESC_bitset_func();
mDemo_Set_ListenAble();
return TRUE;
}
typedef void (*aESC_TALK_PROC)(EVENT_SONCHO_ACTOR*, GAME*);
static int aESC_talk_end_chk(ACTOR* actorx, GAME* game) {
static aESC_TALK_PROC proc[aESC_TALK_NUM] = {
(aESC_TALK_PROC)&none_proc1,
&aESC_talk_select,
&aESC_talk_secand
};
EVENT_SONCHO_ACTOR* soncho = (EVENT_SONCHO_ACTOR*)actorx;
int res = FALSE;
(*proc[soncho->talk_state])(soncho, game);
if (mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE) {
res = TRUE;
}
return res;
}
static void aESC_actor_move(ACTOR* actorx, GAME* game) {
(*Common_Get(clip).npc_clip->move_proc)(actorx, game);
}