mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-05-22 22:24:16 -04:00
Implement & link ac_tokyoso_control
This commit is contained in:
+1
-1
@@ -1070,7 +1070,7 @@ config.libs = [
|
||||
Object(Matching, "actor/ac_super.c"),
|
||||
Object(Matching, "actor/ac_tama.c"),
|
||||
Object(Matching, "actor/ac_tent.c"),
|
||||
Object(NonMatching, "actor/ac_tokyoso_control.c"),
|
||||
Object(Matching, "actor/ac_tokyoso_control.c"),
|
||||
Object(Matching, "actor/ac_tools.c"),
|
||||
Object(Matching, "actor/ac_toudai.c"),
|
||||
Object(Matching, "actor/ac_train0.c"),
|
||||
|
||||
@@ -8,20 +8,82 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define aTKC_LAP_NUM 4
|
||||
#define aTKC_SUBLAP_NUM (2 * aTKC_LAP_NUM) // split into half of the circuit
|
||||
#define aTKC_NPC_NUM 2
|
||||
|
||||
#define aTKC_ANGLE_FOR_LAP_COMPLETION 4000 // approximately 22 degrees
|
||||
|
||||
#define aTKC_FLAG_5 (1 << 5)
|
||||
#define aTKC_FLAG_6 (1 << 6)
|
||||
#define aTKC_FLAG_7 (1 << 7)
|
||||
#define aTKC_FLAG_8 (1 << 8)
|
||||
#define aTKC_FLAG_9 (1 << 9)
|
||||
#define aTKC_FLAG_RACE_ACTIVE (1 << 10)
|
||||
#define aTKC_FLAG_11 (1 << 11)
|
||||
#define aTKC_FLAG_12 (1 << 12)
|
||||
#define aTKC_FLAG_13 (1 << 13)
|
||||
#define aTKC_FLAG_14 (1 << 14)
|
||||
#define aTKC_FLAG_15 (1 << 15)
|
||||
|
||||
#define aTKC_MASK_13_14 (aTKC_FLAG_13 | aTKC_FLAG_14)
|
||||
|
||||
enum {
|
||||
aTKC_GOAL_NONE,
|
||||
aTKC_GOAL_WON,
|
||||
aTKC_GOAL_LOSE,
|
||||
|
||||
aTKC_GOAL_NUM
|
||||
};
|
||||
|
||||
typedef struct ac_tokyoso_event_s {
|
||||
u8 _00;
|
||||
u8 _01;
|
||||
u16 flags;
|
||||
s16 pos_04[3];
|
||||
s16 yasiro_pos[3]; // shrine pos (wishing well in AC and e+)
|
||||
s16 pos_0A[2][2];
|
||||
s16 angle[2];
|
||||
s16 pos_16[2];
|
||||
u8 _1A[2];
|
||||
u8 _1C[2];
|
||||
s16 next_angle[2];
|
||||
u8 lap[2];
|
||||
u8 goal[2];
|
||||
} aEv_tokyoso_c;
|
||||
|
||||
typedef void (*aTKC_NEXT_RUN_PROC)(ACTOR* actorx);
|
||||
typedef s16 (*aTKC_GET_ANGLE_PROC)(ACTOR* actorx);
|
||||
typedef void (*aTKC_RUN_PROC)(ACTOR* actorx);
|
||||
typedef s16 (*aTKC_RUN_CHECK_PROC)(ACTOR* actorx);
|
||||
typedef s16 (*aTKC_TOP_CHECK_PROC)(ACTOR* actorx);
|
||||
typedef s16 (*aTKC_GOAL_CHECK_PROC)(ACTOR* actorx);
|
||||
typedef void (*aTKC_NPC1_THINK_INIT_PROC)(ACTOR* actorx, GAME_PLAY* play, u8 type);
|
||||
typedef void (*aTKC_NEXT_POS_PROC)(ACTOR* actorx, int idx);
|
||||
typedef void (*aTKC_NEXT_WARMUP_PROC)(ACTOR* actorx);
|
||||
typedef void (*aTKC_SET_TALK_REQUEST_PROC)(ACTOR* actorx);
|
||||
|
||||
typedef struct tokyoso_control_clip_s {
|
||||
aTKC_NEXT_RUN_PROC next_run_proc;
|
||||
aTKC_GET_ANGLE_PROC get_angle_proc;
|
||||
aTKC_RUN_PROC run_proc;
|
||||
aTKC_RUN_CHECK_PROC run_check_proc;
|
||||
aTKC_TOP_CHECK_PROC top_check_proc;
|
||||
aTKC_GOAL_CHECK_PROC goal_check_proc;
|
||||
aTKC_NPC1_THINK_INIT_PROC npc1_think_init_proc;
|
||||
aTKC_NEXT_POS_PROC next_pos_proc;
|
||||
aTKC_NEXT_WARMUP_PROC next_warmup_proc;
|
||||
aTKC_SET_TALK_REQUEST_PROC set_talk_request_proc;
|
||||
} aTKC_clip_c;
|
||||
|
||||
typedef struct tokyoso_control_actor_s TOKYOSO_CONTROL_ACTOR;
|
||||
|
||||
typedef void (*aTKC_PROC)(TOKYOSO_CONTROL_ACTOR* actor, GAME_PLAY* play);
|
||||
|
||||
struct tokyoso_control_actor_s {
|
||||
ACTOR actor_class;
|
||||
aTKC_clip_c clip;
|
||||
aTKC_PROC act_proc;
|
||||
int action;
|
||||
s16 timer;
|
||||
};
|
||||
|
||||
extern ACTOR_PROFILE Tokyoso_Control_Profile;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,13 +1,33 @@
|
||||
#ifndef AC_TOKYOSO_NPC1_H
|
||||
#define AC_TOKYOSO_NPC1_H
|
||||
|
||||
#include "lb_reki.h"
|
||||
#include "types.h"
|
||||
#include "m_actor.h"
|
||||
#include "ac_npc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct tokyoso_npc1_actor_s TOKYOSO_NPC1_ACTOR;
|
||||
|
||||
// TODO: finish this
|
||||
struct tokyoso_npc1_actor_s {
|
||||
NPC_ACTOR npc_class;
|
||||
void* think_proc;
|
||||
int msg_start_no;
|
||||
f32 speed;
|
||||
s16 _9A0;
|
||||
s16 start_pos[2];
|
||||
s16 timer;
|
||||
u8 _9A8;
|
||||
u8 _9A9;
|
||||
u8 _9AA;
|
||||
u8 talk_idx;
|
||||
u8 _9AC;
|
||||
};
|
||||
|
||||
extern ACTOR_PROFILE Tokyoso_Npc1_Profile;
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -15,4 +35,3 @@ extern ACTOR_PROFILE Tokyoso_Npc1_Profile;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+2
-1
@@ -37,6 +37,7 @@
|
||||
#include "ac_mikanbox_clip.h"
|
||||
#include "ac_needlework_indoor_clip.h"
|
||||
#include "ac_countdown_clip.h"
|
||||
#include "ac_tokyoso_control.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -90,7 +91,7 @@ typedef struct clip_s {
|
||||
/* 0x0C0 */ aGRGR_clip_c* garagara_clip;
|
||||
/* 0x0C4 */ aHTMD_clip_c* hatumode_clip;
|
||||
/* 0x0C8 */ void* shrine_clip;
|
||||
/* 0x0CC */ void* _0CC;
|
||||
/* 0x0CC */ aTKC_clip_c* tokyoso_clip;
|
||||
/* 0x0D0 */ aCOU_Clip_c* countdown_clip;
|
||||
/* 0x0D4 */ CLIP_NONE_PROC ball_redma_proc; /* removed in DnM+ */
|
||||
/* 0x0D8 */ aMKBC_Clip_c* mikanbox_clip;
|
||||
|
||||
@@ -0,0 +1,348 @@
|
||||
static int aTKN1_set_request_act(TOKYOSO_NPC1_ACTOR* actor, u8 prio, u8 idx, u8 type, u16 obj, s16 move_x, s16 move_z) {
|
||||
int ret = FALSE;
|
||||
|
||||
if (prio >= actor->npc_class.request.act_priority) {
|
||||
u16 arg_data[aNPC_REQUEST_ARG_NUM];
|
||||
|
||||
bzero(arg_data, sizeof(arg_data));
|
||||
arg_data[0] = obj;
|
||||
arg_data[2] = move_x;
|
||||
arg_data[3] = move_z;
|
||||
|
||||
actor->npc_class.request.act_priority = prio;
|
||||
actor->npc_class.request.act_idx = idx;
|
||||
actor->npc_class.request.act_type = type;
|
||||
mem_copy((u8*)actor->npc_class.request.act_args, (u8*)arg_data, sizeof(arg_data));
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void aTKN1_normal_wait_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
aTKN1_set_request_act(actor, 4, aNPC_ACT_WAIT, aNPC_ACT_TYPE_DEFAULT, aNPC_ACT_OBJ_DEFAULT, 0, 0);
|
||||
}
|
||||
|
||||
static void aTKN1_wait_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
actor->npc_class.action.idx = aNPC_ACT_WAIT;
|
||||
aTKN1_normal_wait_init(actor, play);
|
||||
}
|
||||
|
||||
static void aTKN1_run_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
aTKN1_set_request_act(actor, 4, aNPC_ACT_RUN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, actor->start_pos[0], actor->start_pos[1]);
|
||||
actor->npc_class.actor_class.status_data.weight = MASSTYPE_HEAVY-4;
|
||||
actor->npc_class.talk_info.default_animation = aNPC_ANIM_ASIHUMI1;
|
||||
actor->npc_class.talk_info.turn = aNPC_TALK_TURN_NORMAL;
|
||||
}
|
||||
|
||||
static void aTKN1_turn_d_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
ACTOR* actorx = (ACTOR*)actor;
|
||||
|
||||
aTKN1_set_request_act(actor, 4, aNPC_ACT_TURN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, actorx->world.position.x, actorx->world.position.z - 10.0f);
|
||||
}
|
||||
|
||||
static void aTKN1_turn_f_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
ACTOR* actorx = (ACTOR*)actor;
|
||||
|
||||
aTKN1_set_request_act(actor, 4, aNPC_ACT_TURN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, actorx->world.position.x, actorx->world.position.z + 10.0f);
|
||||
}
|
||||
|
||||
static void aTKN1_turn_l_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
ACTOR* actorx = (ACTOR*)actor;
|
||||
|
||||
aTKN1_set_request_act(actor, 4, aNPC_ACT_TURN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, actorx->world.position.x - 10.0f, actorx->world.position.z);
|
||||
}
|
||||
|
||||
static void aTKN1_turn_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
aTKN1_set_request_act(actor, 4, aNPC_ACT_TURN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, actor->start_pos[0], actor->start_pos[1]);
|
||||
actor->npc_class.condition_info.demo_flg &= ~(aNPC_COND_DEMO_SKIP_MOVE_Y | aNPC_COND_DEMO_SKIP_BGCHECK);
|
||||
}
|
||||
|
||||
static void aTKN1_run_turn_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
aTKC_clip_next_run((ACTOR*)actor);
|
||||
aTKN1_turn_init(actor, play);
|
||||
actor->npc_class.talk_info.default_animation = aNPC_ANIM_ASIHUMI1;
|
||||
actor->npc_class.talk_info.turn = aNPC_TALK_TURN_NORMAL;
|
||||
}
|
||||
|
||||
static void aTKN1_warmup_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
NPC_CLIP->animation_init_proc((ACTOR*)actor, aNPC_ANIM_WARMUP1, FALSE);
|
||||
tokyoso->flags &= ~(aTKC_FLAG_5 << ((actor->npc_class.actor_class.npc_id - SP_NPC_EV_TOKYOSO_0) & 1));
|
||||
actor->_9A0 = 240;
|
||||
}
|
||||
|
||||
static void aTKN1_ready_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
aTKN1_wait_init(actor, play);
|
||||
NPC_CLIP->animation_init_proc((ACTOR*)actor, aNPC_ANIM_READY1, FALSE);
|
||||
actor->npc_class.talk_info.default_animation = aNPC_ANIM_READY1;
|
||||
actor->npc_class.talk_info.turn = aNPC_TALK_TURN_NONE;
|
||||
}
|
||||
|
||||
static void aTKN1_kokeru_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
NPC_CLIP->animation_init_proc((ACTOR*)actor, aNPC_ANIM_KOKERU1, FALSE);
|
||||
actor->npc_class.draw.main_animation.keyframe.frame_control.mode = cKF_FRAMECONTROL_STOP;
|
||||
actor->npc_class.movement.speed.max_speed = 0.0f;
|
||||
actor->npc_class.movement.speed.deceleration = 0.2f;
|
||||
actor->npc_class.movement.mv_add_angl = 0;
|
||||
actor->npc_class.talk_info.default_animation = aNPC_ANIM_KOKERU1;
|
||||
actor->npc_class.talk_info.turn = aNPC_TALK_TURN_NONE;
|
||||
}
|
||||
|
||||
static void aTKN1_getup_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
NPC_CLIP->animation_init_proc((ACTOR*)actor, aNPC_ANIM_KOKERU_GETUP1, FALSE);
|
||||
actor->npc_class.draw.main_animation.keyframe.frame_control.mode = cKF_FRAMECONTROL_STOP;
|
||||
actor->npc_class.movement.speed.deceleration = 0.6f;
|
||||
actor->npc_class.talk_info.default_animation = aNPC_ANIM_KOKERU_GETUP1;
|
||||
actor->npc_class.talk_info.turn = aNPC_TALK_TURN_NONE;
|
||||
}
|
||||
|
||||
static void aTKN1_goal_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
ACTOR* actorx = (ACTOR*)actor;
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
actor->npc_class.actor_class.status_data.weight = MASSTYPE_HEAVY;
|
||||
aTKN1_turn_f_init(actor, play);
|
||||
actor->npc_class.talk_info.default_animation = aNPC_ANIM_WAIT1;
|
||||
actor->npc_class.talk_info.turn = aNPC_TALK_TURN_NORMAL;
|
||||
tokyoso->_01 |= (u8)(1 << ((2 + actorx->npc_id - SP_NPC_EV_TOKYOSO_0) & 3));
|
||||
}
|
||||
|
||||
static void aTKN1_goal1_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
aTKN1_wait_init(actor, play);
|
||||
NPC_CLIP->animation_init_proc((ACTOR*)actor, aNPC_ANIM_BANZAI1, FALSE);
|
||||
actor->npc_class.draw.main_animation.keyframe.frame_control.mode = cKF_FRAMECONTROL_REPEAT;
|
||||
}
|
||||
|
||||
static void aTKN1_goal2_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
aTKN1_wait_init(actor, play);
|
||||
NPC_CLIP->animation_init_proc((ACTOR*)actor, aNPC_ANIM_TIRED1, FALSE);
|
||||
actor->npc_class.draw.main_animation.keyframe.frame_control.mode = cKF_FRAMECONTROL_REPEAT;
|
||||
}
|
||||
|
||||
static void aTKN1_kansen_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
aTKN1_normal_wait_init(actor, play);
|
||||
actor->npc_class.condition_info.demo_flg |= (aNPC_COND_DEMO_SKIP_BGCHECK | aNPC_COND_DEMO_SKIP_MOVE_Y);
|
||||
}
|
||||
|
||||
static void aTKN1_omedeto_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
aTKN1_wait_init(actor, play);
|
||||
NPC_CLIP->animation_init_proc((ACTOR*)actor, aNPC_ANIM_CLAP1, FALSE);
|
||||
actor->npc_class.draw.main_animation.keyframe.frame_control.mode = cKF_FRAMECONTROL_REPEAT;
|
||||
actor->npc_class.condition_info.demo_flg |= (aNPC_COND_DEMO_SKIP_BGCHECK | aNPC_COND_DEMO_SKIP_MOVE_Y);
|
||||
}
|
||||
|
||||
static void aTKN1_omedeto_af_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
actor->npc_class.action.idx = aNPC_ACT_RUN;
|
||||
aTKN1_normal_wait_init(actor, play);
|
||||
actor->npc_class.condition_info.demo_flg |= (aNPC_COND_DEMO_SKIP_BGCHECK | aNPC_COND_DEMO_SKIP_MOVE_Y);
|
||||
}
|
||||
|
||||
static void aTKN1_move_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
aTKN1_set_request_act(actor, 4, aNPC_ACT_WALK, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, actor->start_pos[0], actor->start_pos[1]);
|
||||
}
|
||||
|
||||
static void aTKN1_lookl_init(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) {
|
||||
ACTOR* actorx = (ACTOR*)actor;
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
aTKN1_turn_l_init(actor, play);
|
||||
tokyoso->flags &= ~(aTKC_FLAG_11 << ((actorx->npc_id - SP_NPC_EV_TOKYOSO_0) & 1));
|
||||
}
|
||||
|
||||
typedef void (*aTKN1_THINK_INIT_PROC)(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play);
|
||||
// clang-format off
|
||||
static aTKN1_THINK_INIT_PROC init_table[] = {
|
||||
(aTKN1_THINK_INIT_PROC)none_proc1,
|
||||
aTKN1_normal_wait_init,
|
||||
aTKN1_wait_init,
|
||||
aTKN1_run_init,
|
||||
aTKN1_turn_d_init,
|
||||
aTKN1_turn_l_init,
|
||||
aTKN1_turn_f_init,
|
||||
aTKN1_turn_init,
|
||||
aTKN1_warmup_init,
|
||||
aTKN1_ready_init,
|
||||
aTKN1_kokeru_init,
|
||||
aTKN1_getup_init,
|
||||
aTKN1_goal_init,
|
||||
aTKN1_goal1_init,
|
||||
aTKN1_goal2_init,
|
||||
aTKN1_omedeto_init,
|
||||
aTKN1_move_init,
|
||||
aTKN1_lookl_init,
|
||||
aTKN1_run_turn_init,
|
||||
aTKN1_kansen_init,
|
||||
aTKN1_omedeto_af_init,
|
||||
};
|
||||
// clang-fomrat on
|
||||
|
||||
static void aTKC_clip_npc1_think_init(ACTOR* actorx, GAME_PLAY* play, u8 think_init) {
|
||||
(*init_table[think_init])((TOKYOSO_NPC1_ACTOR*)actorx, play);
|
||||
}
|
||||
|
||||
static void aTKC_clip_next_run(ACTOR* actorx) {
|
||||
TOKYOSO_NPC1_ACTOR* actor = (TOKYOSO_NPC1_ACTOR*)actorx;
|
||||
s16 angle = aTKC_clip_get_angle(actorx);
|
||||
f32 f;
|
||||
int idx = (actorx->npc_id - SP_NPC_EV_TOKYOSO_0) & 1;
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
angle += (s16)(aTKC_ANGLE_FOR_LAP_COMPLETION + RANDOM_F(aTKC_ANGLE_FOR_LAP_COMPLETION));
|
||||
f = (160.0f + RANDOM_F(20.0f)) - idx * 35.0f;
|
||||
|
||||
actor->speed = (4.0f + f * (1.0f / 90.0f)) - idx * 0.5f;
|
||||
if (aTKC_clip_top_check(actorx)) {
|
||||
actor->speed -= 1.0f;
|
||||
}
|
||||
|
||||
actor->start_pos[0] = tokyoso->yasiro_pos[0] + f * cos_s(angle);
|
||||
actor->start_pos[1] = tokyoso->yasiro_pos[1] - f * sin_s(angle);
|
||||
tokyoso->next_angle[idx] = angle;
|
||||
actor->npc_class.movement.speed.deceleration = 0.6f;
|
||||
|
||||
if (tokyoso->lap[idx] == aTKC_SUBLAP_NUM && tokyoso->next_angle[idx] > 0) {
|
||||
actor->start_pos[0] = (tokyoso->yasiro_pos[0] + 220.0f) - idx * 60.0f + (RANDOM_F(10.0f) - 5.0f);
|
||||
actor->start_pos[1] = (tokyoso->yasiro_pos[1] - 130.0f) + idx * 60.0f + (RANDOM_F(10.0f) - 5.0f);
|
||||
}
|
||||
|
||||
actor->timer = 300;
|
||||
}
|
||||
|
||||
static s16 aTKC_clip_get_angle(ACTOR* actorx) {
|
||||
f32 dx;
|
||||
f32 dz;
|
||||
s16 angle;
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
dx = (tokyoso->yasiro_pos[0] + 20) - actorx->world.position.x;
|
||||
dz = tokyoso->yasiro_pos[1] - actorx->world.position.z;
|
||||
angle = atans_table(dz, dx);
|
||||
return DEG2SHORT_ANGLE(90.0f) + angle;
|
||||
}
|
||||
|
||||
static void aTKC_clip_run_proc(ACTOR* actorx) {
|
||||
int idx = (actorx->npc_id - SP_NPC_EV_TOKYOSO_0) & 1;
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
tokyoso->pos_0A[idx][0] = actorx->world.position.x;
|
||||
tokyoso->pos_0A[idx][1] = actorx->world.position.z;
|
||||
tokyoso->angle[idx] = aTKC_clip_get_angle(actorx);
|
||||
}
|
||||
|
||||
static s16 aTKC_clip_run_check(ACTOR* actorx) {
|
||||
int idx = (actorx->npc_id - SP_NPC_EV_TOKYOSO_0) & 1;
|
||||
s16 angle;
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
TOKYOSO_NPC1_ACTOR* actor = (TOKYOSO_NPC1_ACTOR*)actorx;
|
||||
|
||||
if (actor->timer > 0) {
|
||||
actor->timer--;
|
||||
if (actor->timer == 0) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (tokyoso->lap[idx] == aTKC_SUBLAP_NUM && tokyoso->next_angle[idx] > 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
angle = tokyoso->angle[idx] - tokyoso->next_angle[idx];
|
||||
|
||||
#ifdef BUGFIXES
|
||||
if (angle > DEG2SHORT_ANGLE2(-22.5f) && angle < DEG2SHORT_ANGLE2(22.5f)) {
|
||||
#else
|
||||
// @BUG - did the devs miss a hex specifier here? Shouldn't this be angle >= -[0x]1000?
|
||||
if (angle > -1000 && angle < DEG2SHORT_ANGLE2(22.5f)) {
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static s16 aTKC_clip_top_check(ACTOR* actorx) {
|
||||
int idx0 = (actorx->npc_id - SP_NPC_EV_TOKYOSO_0) & 1;
|
||||
int idx1 = (idx0 + 1) & 1;
|
||||
s16 angle;
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
if ((tokyoso->flags & aTKC_FLAG_RACE_ACTIVE) == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
angle = tokyoso->angle[idx0] - tokyoso->angle[idx1];
|
||||
if (tokyoso->lap[idx0] > tokyoso->lap[idx1] || (tokyoso->lap[idx0] == tokyoso->lap[idx1] && angle > 0)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static s16 aTKC_clip_goal_check(ACTOR* actorx) {
|
||||
int idx = (actorx->npc_id - SP_NPC_EV_TOKYOSO_0) & 1;
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
if ((tokyoso->flags & aTKC_FLAG_RACE_ACTIVE) == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (tokyoso->goal[idx] == aTKC_GOAL_NONE) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return tokyoso->goal[idx];
|
||||
}
|
||||
|
||||
static void aTKC_clip_next_pos(ACTOR* actorx, int idx) {
|
||||
static s16 tableX[] = { 200, 160, 280, 280 };
|
||||
static s16 tableZ[] = { 0, 0, 40, 0 };
|
||||
TOKYOSO_NPC1_ACTOR* actor = (TOKYOSO_NPC1_ACTOR*)actorx;
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
actor->start_pos[0] = tokyoso->yasiro_pos[0] + tableX[idx];
|
||||
actor->start_pos[1] = tokyoso->yasiro_pos[1] + tableZ[idx];
|
||||
}
|
||||
|
||||
static void aTKC_clip_next_warmup(ACTOR* actorx) {
|
||||
static s16 tableX[] = { 200, 160 };
|
||||
static f32 tableXR[] = { 40.0f, -40.0f };
|
||||
int idx = (actorx->npc_id - SP_NPC_EV_TOKYOSO_0) & 1;
|
||||
TOKYOSO_NPC1_ACTOR* actor = (TOKYOSO_NPC1_ACTOR*)actorx;
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
actor->start_pos[0] = tokyoso->yasiro_pos[0] + tableX[idx] + (s16)RANDOM_F(tableXR[idx]);
|
||||
actor->start_pos[1] = tokyoso->yasiro_pos[1] + RANDOM_F(80.0f) - 40.0f;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int msg_no;
|
||||
u8 turn_flag;
|
||||
u8 camera_type;
|
||||
} aTCK_npc1_talk_data_c;
|
||||
|
||||
static void aTKC_clip_set_talk_request(ACTOR* actorx) {
|
||||
static aTCK_npc1_talk_data_c dt_tbl[] = {
|
||||
{14, FALSE, CAMERA2_PROCESS_TALK},
|
||||
{ 2, FALSE, CAMERA2_PROCESS_TALK},
|
||||
{14, FALSE, CAMERA2_PROCESS_TALK},
|
||||
{ 4, FALSE, CAMERA2_PROCESS_TALK},
|
||||
{ 6, TRUE, CAMERA2_PROCESS_TALK},
|
||||
{ 8, TRUE, CAMERA2_PROCESS_TALK},
|
||||
{ 8, TRUE, CAMERA2_PROCESS_TALK},
|
||||
{10, FALSE, CAMERA2_PROCESS_TALK},
|
||||
{10, FALSE, CAMERA2_PROCESS_TALK},
|
||||
{12, TRUE, CAMERA2_PROCESS_TALK},
|
||||
{12, TRUE, CAMERA2_PROCESS_TALK},
|
||||
{12, TRUE, CAMERA2_PROCESS_TALK},
|
||||
{12, TRUE, CAMERA2_PROCESS_TALK},
|
||||
};
|
||||
|
||||
TOKYOSO_NPC1_ACTOR* actor = (TOKYOSO_NPC1_ACTOR*)actorx;
|
||||
aTCK_npc1_talk_data_c* data_p = &dt_tbl[actor->talk_idx];
|
||||
|
||||
mDemo_Set_msg_num(actor->msg_start_no + data_p->msg_no + RANDOM(2));
|
||||
mDemo_Set_talk_turn(data_p->turn_flag);
|
||||
mDemo_Set_camera(data_p->camera_type);
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
#include "ac_tokyoso_control.h"
|
||||
#include "m_actor.h"
|
||||
#include "m_actor_type.h"
|
||||
#include "m_common_data.h"
|
||||
#include "m_event.h"
|
||||
#include "m_field_info.h"
|
||||
#include "m_name_table.h"
|
||||
#include "ac_tokyoso_npc1.h"
|
||||
#include "libultra/libultra.h"
|
||||
|
||||
enum {
|
||||
aTKC_ACT_WAIT,
|
||||
aTKC_ACT_WAIT2,
|
||||
aTKC_ACT_STRECH,
|
||||
aTKC_ACT_READY,
|
||||
aTKC_ACT_SET,
|
||||
aTKC_ACT_GO,
|
||||
aTKC_ACT_GOAL,
|
||||
aTKC_ACT_IREKAE_1,
|
||||
aTKC_ACT_IREKAE_2,
|
||||
|
||||
aTKC_ACT_NUM
|
||||
};
|
||||
|
||||
static void aTKC_actor_ct(ACTOR* actorx, GAME* game);
|
||||
static void aTKC_actor_dt(ACTOR* actorx, GAME* game);
|
||||
static void aTKC_actor_move(ACTOR* actorx, GAME* game);
|
||||
|
||||
// clang-format off
|
||||
ACTOR_PROFILE Tokyoso_Control_Profile = {
|
||||
mAc_PROFILE_TOKYOSO_CONTROL,
|
||||
ACTOR_PART_CONTROL,
|
||||
ACTOR_STATE_NO_MOVE_WHILE_CULLED,
|
||||
EMPTY_NO,
|
||||
ACTOR_OBJ_BANK_KEEP,
|
||||
sizeof(TOKYOSO_CONTROL_ACTOR),
|
||||
aTKC_actor_ct,
|
||||
aTKC_actor_dt,
|
||||
aTKC_actor_move,
|
||||
mActor_NONE_PROC1,
|
||||
NULL,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static void aTKC_setupAction(TOKYOSO_CONTROL_ACTOR* actor, int action);
|
||||
|
||||
// clip declarations
|
||||
static void aTKC_clip_next_run(ACTOR* actorx);
|
||||
static s16 aTKC_clip_get_angle(ACTOR* actorx);
|
||||
static void aTKC_clip_run_proc(ACTOR* actorx);
|
||||
static s16 aTKC_clip_run_check(ACTOR* actorx);
|
||||
static s16 aTKC_clip_top_check(ACTOR* actorx);
|
||||
static s16 aTKC_clip_goal_check(ACTOR* actorx);
|
||||
static void aTKC_clip_npc1_think_init(ACTOR* actorx, GAME_PLAY* play, u8 type);
|
||||
static void aTKC_clip_next_pos(ACTOR* actorx, int idx);
|
||||
static void aTKC_clip_next_warmup(ACTOR* actorx);
|
||||
static void aTKC_clip_set_talk_request(ACTOR* actorx);
|
||||
|
||||
static void aTKC_actor_ct(ACTOR* actorx, GAME* game) {
|
||||
TOKYOSO_CONTROL_ACTOR* actor = (TOKYOSO_CONTROL_ACTOR*)actorx;
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
if (tokyoso == NULL) {
|
||||
tokyoso = (aEv_tokyoso_c*)mEv_reserve_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
tokyoso->_00 = 0;
|
||||
tokyoso->flags = 0;
|
||||
}
|
||||
|
||||
actor->clip.next_run_proc = aTKC_clip_next_run;
|
||||
actor->clip.get_angle_proc = aTKC_clip_get_angle;
|
||||
actor->clip.run_proc = aTKC_clip_run_proc;
|
||||
actor->clip.run_check_proc = aTKC_clip_run_check;
|
||||
actor->clip.top_check_proc = aTKC_clip_top_check;
|
||||
actor->clip.goal_check_proc = aTKC_clip_goal_check;
|
||||
actor->clip.npc1_think_init_proc = aTKC_clip_npc1_think_init;
|
||||
actor->clip.next_pos_proc = aTKC_clip_next_pos;
|
||||
actor->clip.next_warmup_proc = aTKC_clip_next_warmup;
|
||||
actor->clip.set_talk_request_proc = aTKC_clip_set_talk_request;
|
||||
CLIP(tokyoso_clip) = &actor->clip;
|
||||
aTKC_setupAction(actor, aTKC_ACT_WAIT);
|
||||
}
|
||||
|
||||
static void aTKC_actor_dt(ACTOR* actorx, GAME* game) {
|
||||
CLIP(tokyoso_clip) = NULL;
|
||||
mEv_actor_dying_message(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, actorx);
|
||||
}
|
||||
|
||||
static void aTKC_actor_move(ACTOR* actorx, GAME* game) {
|
||||
TOKYOSO_CONTROL_ACTOR* actor = (TOKYOSO_CONTROL_ACTOR*)actorx;
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
if (tokyoso->_00 == 3 && actor->action != aTKC_ACT_WAIT2) {
|
||||
aTKC_setupAction(actor, aTKC_ACT_WAIT2);
|
||||
} else {
|
||||
actor->act_proc(actor, (GAME_PLAY*)game);
|
||||
}
|
||||
}
|
||||
|
||||
static void aTKC_irekae_2(TOKYOSO_CONTROL_ACTOR* actor, GAME_PLAY* play) {
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
if ((tokyoso->flags & aTKC_FLAG_11) == 0) {
|
||||
aTKC_setupAction(actor, aTKC_ACT_STRECH);
|
||||
actor->timer = 600;
|
||||
}
|
||||
}
|
||||
|
||||
static void aTKC_irekae_1(TOKYOSO_CONTROL_ACTOR* actor, GAME_PLAY* play) {
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
if ((tokyoso->flags & aTKC_FLAG_12) == 0) {
|
||||
aTKC_setupAction(actor, aTKC_ACT_IREKAE_2);
|
||||
tokyoso->flags |= aTKC_FLAG_5;
|
||||
tokyoso->flags |= aTKC_FLAG_11;
|
||||
}
|
||||
}
|
||||
|
||||
static void aTKC_goal(TOKYOSO_CONTROL_ACTOR* actor, GAME_PLAY* play) {
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
if ((tokyoso->flags & aTKC_MASK_13_14) == aTKC_MASK_13_14) {
|
||||
if (actor->timer > 0) {
|
||||
actor->timer--;
|
||||
} else {
|
||||
aTKC_setupAction(actor, aTKC_ACT_IREKAE_1);
|
||||
tokyoso->flags |= aTKC_FLAG_6;
|
||||
tokyoso->flags |= aTKC_FLAG_12;
|
||||
tokyoso->flags &= ~aTKC_FLAG_RACE_ACTIVE;
|
||||
tokyoso->flags &= ~aTKC_MASK_13_14;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void aTKC_go(TOKYOSO_CONTROL_ACTOR* actor, GAME_PLAY* play) {
|
||||
int i;
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
for (i = 0; i < aTKC_NPC_NUM; i++) {
|
||||
if (tokyoso->lap[i] & 1) {
|
||||
if (tokyoso->angle[i] < -aTKC_ANGLE_FOR_LAP_COMPLETION) {
|
||||
tokyoso->lap[i]++;
|
||||
}
|
||||
} else {
|
||||
if (tokyoso->angle[i] > aTKC_ANGLE_FOR_LAP_COMPLETION) {
|
||||
tokyoso->lap[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
if (tokyoso->lap[i] > aTKC_SUBLAP_NUM && tokyoso->goal[i] == aTKC_GOAL_NONE) {
|
||||
if (tokyoso->goal[(i + 1) & 1] == aTKC_GOAL_NONE) {
|
||||
tokyoso->goal[i] = aTKC_GOAL_WON;
|
||||
} else {
|
||||
aTKC_setupAction(actor, aTKC_ACT_GOAL);
|
||||
tokyoso->goal[i] = aTKC_GOAL_LOSE;
|
||||
actor->timer = 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void aTKC_set(TOKYOSO_CONTROL_ACTOR* actor, GAME_PLAY* play) {
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
if ((tokyoso->flags & (aTKC_FLAG_7 | aTKC_FLAG_8 | aTKC_FLAG_9)) == 0) {
|
||||
aTKC_setupAction(actor, aTKC_ACT_GO); // @BUG - this is called twice
|
||||
tokyoso->flags |= aTKC_FLAG_RACE_ACTIVE;
|
||||
tokyoso->lap[0] = tokyoso->lap[1] = 0;
|
||||
tokyoso->goal[0] = tokyoso->goal[1] = aTKC_GOAL_NONE;
|
||||
aTKC_setupAction(actor, aTKC_ACT_GO);
|
||||
}
|
||||
}
|
||||
|
||||
static void aTKC_ready(TOKYOSO_CONTROL_ACTOR* actor, GAME_PLAY* play) {
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
if ((tokyoso->flags & (aTKC_FLAG_7 | aTKC_FLAG_8 | aTKC_FLAG_9)) == 0) {
|
||||
if (actor->timer > 0) {
|
||||
actor->timer--;
|
||||
} else {
|
||||
aTKC_setupAction(actor, aTKC_ACT_SET);
|
||||
tokyoso->flags |= (aTKC_FLAG_7 | aTKC_FLAG_8 | aTKC_FLAG_9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void aTKC_strech(TOKYOSO_CONTROL_ACTOR* actor, GAME_PLAY* play) {
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
if ((tokyoso->flags & (aTKC_FLAG_5 | aTKC_FLAG_6)) == 0) {
|
||||
if (actor->timer > 0) {
|
||||
actor->timer--;
|
||||
} else {
|
||||
actor->timer = 120;
|
||||
aTKC_setupAction(actor, aTKC_ACT_READY);
|
||||
tokyoso->flags |= (aTKC_FLAG_7 | aTKC_FLAG_8 | aTKC_FLAG_9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void aTKC_wait2(TOKYOSO_CONTROL_ACTOR* actor, GAME_PLAY* play) {
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
if (tokyoso->_00 == 0) {
|
||||
tokyoso->_00 = 1;
|
||||
aTKC_setupAction(actor, aTKC_ACT_STRECH);
|
||||
actor->timer = 600;
|
||||
}
|
||||
}
|
||||
|
||||
static void aTKC_wait(TOKYOSO_CONTROL_ACTOR* actor, GAME_PLAY* play) {
|
||||
aEv_tokyoso_c* tokyoso = (aEv_tokyoso_c*)mEv_get_save_area(mEv_EVENT_SPORTS_FAIR_FOOT_RACE, 8);
|
||||
|
||||
if (mFI_SetOyasiroPos(tokyoso->yasiro_pos)) {
|
||||
tokyoso->_00 = 1;
|
||||
aTKC_setupAction(actor, aTKC_ACT_STRECH);
|
||||
actor->timer = 600;
|
||||
}
|
||||
}
|
||||
|
||||
static void aTKC_setupAction(TOKYOSO_CONTROL_ACTOR* actor, int action) {
|
||||
// clang-format off
|
||||
static aTKC_PROC process[] = {
|
||||
aTKC_wait,
|
||||
aTKC_wait2,
|
||||
aTKC_strech,
|
||||
aTKC_ready,
|
||||
aTKC_set,
|
||||
aTKC_go,
|
||||
aTKC_goal,
|
||||
aTKC_irekae_1,
|
||||
aTKC_irekae_2,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
actor->action = action;
|
||||
actor->act_proc = process[action];
|
||||
}
|
||||
|
||||
#include "../src/actor/ac_tokyoso_clip.c_inc"
|
||||
Reference in New Issue
Block a user