Merge pull request #315 from Hexalotl/ac_buggy

Implement & link ac_buggy
This commit is contained in:
Cuyler36
2024-03-25 17:44:39 -04:00
committed by GitHub
6 changed files with 590 additions and 1 deletions
+4
View File
@@ -755,6 +755,10 @@ ac_br_shop.c:
.text: [0x805A856C, 0x805A9474]
.rodata: [0x8064A630, 0x8064A660]
.data: [0x806C4560, 0x806C4688]
ac_buggy.c:
.text: [0x805A9CA0, 0x805AAB3C]
.rodata: [0x8064A6D0, 0x8064A708]
.data: [0x806C4730, 0x806C4858]
ac_douzou.c:
.text: [0x805AD6D8, 0x805AE704]
.rodata: [0x8064A7C0, 0x8064A7E8]
+1 -1
View File
@@ -2,7 +2,7 @@
#define AC_BUGGY_H
#include "types.h"
#include "m_actor.h"
#include "ac_structure.h"
#ifdef __cplusplus
extern "C" {
+1
View File
@@ -2718,6 +2718,7 @@ extern int mNT_check_unknown(mActor_name_t item_no);
#define DUMMY_RESERVE 0xF102
#define DUMMY_SHRINE 0xF103
#define DUMMY_BROKER_SHOP 0xF104
#define DUMMY_BUGGY 0xF105
#define DUMMY_CAR 0xF106
#define DUMMY_RADIO 0xF109
#define DUMMY_YATAI 0xF10A
+129
View File
@@ -0,0 +1,129 @@
#include "ac_buggy.h"
#include "m_name_table.h"
#include "bg_item_h.h"
#include "m_common_data.h"
#include "m_house.h"
#include "m_player_lib.h"
#include "m_demo.h"
#include "ac_intro_demo.h"
#include "m_bgm.h"
#include "sys_matrix.h"
#include "m_rcp.h"
#include "libforest/gbi_extensions.h"
// clang-format off
enum {
aBGY_ACTION_WAIT,
aBGY_ACTION_OPEN_WAIT,
aBGY_ACTION_CLOSE_DOOR,
aBGY_ACTION_OPEN_DOOR,
aBGY_ACTION_NUM
};
// clang-format on
static void aBGY_actor_ct(ACTOR* actor, GAME* game);
static void aBGY_actor_dt(ACTOR* actor, GAME* game);
static void aBGY_actor_init(ACTOR* actor, GAME* game);
static void aBGY_actor_draw(ACTOR* actor, GAME* game);
// clang-format off
ACTOR_PROFILE Buggy_Profile = {
mAc_PROFILE_BUGGY,
ACTOR_PART_ITEM,
ACTOR_STATE_TA_SET,
FORTUNE_TENT,
ACTOR_OBJ_BANK_KEEP,
sizeof(STRUCTURE_ACTOR),
&aBGY_actor_ct,
&aBGY_actor_dt,
&aBGY_actor_init,
&aBGY_actor_draw,
NULL
};
// clang-format on
// clang-format off
static u8 aBGY_shadow_vtx_fix_flg_table[] = {
TRUE, TRUE, FALSE, TRUE,
FALSE, FALSE, TRUE, FALSE,
FALSE, TRUE, TRUE, FALSE,
TRUE, FALSE, FALSE, FALSE
};
// clang-format on
extern Vtx obj_uranai_shadow_v[];
extern Gfx obj_uranai_shadowT_model[];
// clang-format off
static bIT_ShadowData_c aBGY_shadow_data = {
14,
aBGY_shadow_vtx_fix_flg_table,
60.0f,
obj_uranai_shadow_v,
obj_uranai_shadowT_model
};
// clang-format on
extern cKF_Skeleton_R_c cKF_bs_r_obj_s_uranai;
extern cKF_Skeleton_R_c cKF_bs_r_obj_w_uranai;
static void change_FGUnit(STRUCTURE_ACTOR* buggy, int type);
static void aBGY_set_bgOffset(STRUCTURE_ACTOR* buggy, int offs);
static void aBGY_setup_action(STRUCTURE_ACTOR* buggy, int action);
static int aBGY_ctrl_light(STRUCTURE_ACTOR* buggy);
static void aBGY_actor_ct(ACTOR* actor, GAME* game) {
static cKF_Skeleton_R_c* skl[] = { &cKF_bs_r_obj_s_uranai, &cKF_bs_r_obj_w_uranai };
STRUCTURE_ACTOR* buggy;
GAME_PLAY* play;
PLAYER_ACTOR* player;
int winter;
int action;
int x;
int z;
f32 speed;
buggy = (STRUCTURE_ACTOR*)actor;
play = (GAME_PLAY*)game;
player = get_player_actor_withoutCheck(play);
buggy->season = Common_Get(time.season);
winter = buggy->season == mTM_SEASON_WINTER;
cKF_SkeletonInfo_R_ct(&buggy->keyframe, skl[winter], NULL, buggy->work_area, buggy->morph_area);
aBGY_set_bgOffset(buggy, 1);
change_FGUnit(buggy, 1);
x = (int)buggy->actor_class.world.position.x;
z = (int)(buggy->actor_class.world.position.z + 100.0f);
action = aBGY_ACTION_WAIT;
if ((int)player->actor_class.world.position.x == x && (int)player->actor_class.world.position.z == z) {
action = aBGY_ACTION_OPEN_WAIT;
}
aBGY_setup_action(buggy, action);
buggy->actor_class.talk_distance = 80.0;
cKF_SkeletonInfo_R_play(&buggy->keyframe);
buggy->arg0_f = aBGY_ctrl_light(buggy) ? 1.0f : 0.0f;
}
static void aBGY_actor_dt(ACTOR* actor, GAME* game) {
STRUCTURE_ACTOR* buggy;
buggy = (STRUCTURE_ACTOR*)actor;
change_FGUnit(buggy, 0);
cKF_SkeletonInfo_R_dt(&buggy->keyframe);
}
#include "../src/ac_buggy_move.c_inc"
#include "../src/ac_buggy_draw.c_inc"
+124
View File
@@ -0,0 +1,124 @@
extern Gfx obj_s_uranai_window_model[];
extern Gfx obj_w_uranai_window_model[];
static int aBGY_actor_draw_before(GAME* game, cKF_SkeletonInfo_R_c* keyframe, int joint_idx, Gfx** joint_shape,
u8* joint_flags, void* arg, s_xyz* joint_rot, xyz_t* joint_pos) {
STRUCTURE_ACTOR* actor = (STRUCTURE_ACTOR*)arg;
GRAPH* graph = game->graph;
f32 color;
Gfx* gfx;
if (joint_idx == 1) {
OPEN_DISP(graph);
color = actor->arg0_f;
gfx = NOW_POLY_OPA_DISP;
gDPSetPrimColor(gfx++, 0, 0, (int)(0.5f + (255.0f * color)), (int)(0.5f + (255.0f * color)),
(int)(0.5f + (150.0f * color)), 255);
SET_POLY_OPA_DISP(gfx);
CLOSE_DISP(graph);
} else if (joint_idx == 7) {
*joint_shape = NULL;
}
return TRUE;
}
static int aBGY_actor_draw_after(GAME* game, cKF_SkeletonInfo_R_c* keyframe, int joint_idx, Gfx** joint_shape,
u8* joint_flags, void* arg, s_xyz* joint_rot, xyz_t* joint_pos) {
static Gfx* mdl[] = {
obj_s_uranai_window_model,
obj_w_uranai_window_model,
};
STRUCTURE_ACTOR* buggy;
GRAPH* graph;
Mtx* mtx;
int winter;
int l;
int r;
int g;
int b;
Gfx* gfx;
buggy = (STRUCTURE_ACTOR*)arg;
graph = game->graph;
if (joint_idx == 7) {
mtx = _Matrix_to_Mtx_new(graph);
if (mtx != NULL) {
if (buggy->arg0_f > 0.0f) {
r = 255;
g = 255;
b = 150;
l = (0.5f + (120.0f * buggy->arg0_f));
} else {
l = 0;
r = 0;
g = 0;
b = 0;
}
winter = buggy->season == mTM_SEASON_WINTER;
_texture_z_light_fog_prim_shadow(graph);
OPEN_DISP(graph);
gfx = NOW_SHADOW_DISP;
gDPSetPrimColor(gfx++, 0, l, r, g, b, 0);
gSPMatrix(gfx++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(gfx++, mdl[winter]);
SET_SHADOW_DISP(gfx);
CLOSE_DISP(graph);
}
}
return TRUE;
}
static void aBGY_actor_draw(ACTOR* actor, GAME* game) {
STRUCTURE_ACTOR* buggy;
GRAPH* graph;
cKF_SkeletonInfo_R_c* keyframe;
Mtx* mtx;
Gfx* poly_opa;
Gfx* poly_xlu;
buggy = (STRUCTURE_ACTOR*)actor;
graph = game->graph;
keyframe = &buggy->keyframe;
mtx = GRAPH_ALLOC_TYPE(graph, Mtx, (u32)keyframe->skeleton->num_shown_joints);
if (mtx != NULL) {
u16* pal;
pal = Common_Get(clip).structure_clip->get_pal_segment_proc(aSTR_PAL_BUGGY);
OPEN_DISP(graph);
{
_texture_z_light_fog_prim(graph);
poly_opa = NOW_POLY_OPA_DISP;
gSPSegment(poly_opa++, 8, pal);
SET_POLY_OPA_DISP(poly_opa);
}
{
_texture_z_light_fog_prim_xlu(graph);
poly_xlu = NOW_POLY_XLU_DISP;
gSPSegment(poly_xlu++, 8, pal);
SET_POLY_XLU_DISP(poly_xlu);
}
CLOSE_DISP(graph);
cKF_Si3_draw_R_SV(game, keyframe, mtx, &aBGY_actor_draw_before, &aBGY_actor_draw_after, actor);
(*Common_Get(clip).bg_item_clip->draw_shadow_proc)(game, &aBGY_shadow_data, FALSE);
}
}
+331
View File
@@ -0,0 +1,331 @@
extern cKF_Animation_R_c cKF_ba_r_obj_s_uranai;
extern cKF_Animation_R_c cKF_ba_r_obj_w_uranai;
// clang-format off
static Door_data_c aBGY_buggy_door_data = {
SCENE_BUGGY,
mSc_DIRECT_NORTH,
FALSE,
0,
{160,0,300},
EMPTY_NO,
1,
{0,0,0},
};
// clang-format on
static void change_FGUnit(STRUCTURE_ACTOR* buggy, int type) {
int dug;
xyz_t pos;
mActor_name_t* unit_fg;
xyz_t_move(&pos, &buggy->actor_class.world.position);
pos.z += 80.0f;
if (type == FALSE) {
mFI_SetFG_common(EMPTY_NO, pos, TRUE);
return;
}
unit_fg = mFI_GetUnitFG(pos);
if (unit_fg == NULL) {
return;
}
if (mSN_ClearSnowman(unit_fg) == FALSE) {
dug = FALSE;
if ((((*unit_fg >= BURIED_PITFALL_START) && (*unit_fg <= BURIED_PITFALL_END)) || (*unit_fg == SHINE_SPOT))) {
dug = TRUE;
}
if (dug == TRUE) {
mPB_keep_item(bg_item_fg_sub_dig2take_conv(*unit_fg));
mFI_SetFG_common(RSV_NO, pos, 1);
mFI_Wpos2DepositOFF(pos);
} else {
mFI_Wpos2DepositOFF(pos);
mPB_keep_item(*unit_fg);
mFI_SetFG_common(RSV_NO, pos, 1);
}
} else {
mFI_SetFG_common(RSV_NO, pos, 1);
}
}
static void aBGY_set_bgOffset(STRUCTURE_ACTOR* buggy, int offs) {
// clang-format off
static mCoBG_OffsetTable_c height_table_ct[] = {
{ mCoBG_ATTRIBUTE_NONE, 8, 8, 0, 8, 8, 1},
{ mCoBG_ATTRIBUTE_NONE, 8, 8, 8, 8, 8, 0},
{ mCoBG_ATTRIBUTE_NONE, 8, 8, 8, 0, 8, 1},
{ mCoBG_ATTRIBUTE_NONE, 8, 8, 8, 8, 8, 0},
{ mCoBG_ATTRIBUTE_NONE, 8, 8, 8, 8, 8, 0},
{ mCoBG_ATTRIBUTE_NONE, 8, 8, 8, 8, 8, 0},
{ mCoBG_ATTRIBUTE_NONE, 8, 0, 8, 8, 8, 1},
{ mCoBG_ATTRIBUTE_NONE, 8, 8, 8, 8, 8, 0},
{ mCoBG_ATTRIBUTE_NONE, 8, 8, 8, 8, 0, 1}
};
// clang-format on
static mCoBG_OffsetTable_c* height_table[] = { height_table_ct, height_table_ct };
static f32 addX[] = { -mFI_UT_WORLDSIZE_X_F, 0.0f, mFI_UT_WORLDSIZE_X_F };
static f32 addZ[] = { mFI_UT_WORLDSIZE_Z_F, 0.0f, -mFI_UT_WORLDSIZE_Z_F };
mCoBG_OffsetTable_c* offset;
int i;
xyz_t pos;
offset = height_table[offs];
for (i = 0; i < 3; i++) {
pos.z = buggy->actor_class.home.position.z + addZ[i];
pos.x = buggy->actor_class.home.position.x + addX[0];
mCoBG_SetPluss5PointOffset_file(pos, offset[0], __FILE__, 225);
pos.x = buggy->actor_class.home.position.x + addX[1];
mCoBG_SetPluss5PointOffset_file(pos, offset[1], __FILE__, 229);
pos.x = buggy->actor_class.home.position.x + addX[2];
mCoBG_SetPluss5PointOffset_file(pos, offset[2], __FILE__, 233);
offset += 3;
}
}
static void aBGY_rewrite_out_data(ACTOR* actor, GAME_PLAY* play) {
Door_data_c* door_data;
xyz_t pos;
door_data = Common_GetPointer(structure_exit_door_data);
if (play->fb_wipe_mode != 0) {
return;
}
door_data->next_scene_id = Save_Get(scene_no);
door_data->exit_orientation = mSc_DIRECT_SOUTH;
door_data->exit_type = 0;
door_data->extra_data = 3;
pos.x = actor->world.position.x;
pos.y = actor->world.position.y;
pos.z = actor->world.position.z + 100.0f;
door_data->exit_position.x = pos.x;
door_data->exit_position.y = pos.y;
door_data->exit_position.z = pos.z;
door_data->door_actor_name = FORTUNE_TENT;
door_data->wipe_type = 1;
mBGMPsComp_make_ps_wipe(0x2168);
}
static int aBGY_check_player2(GAME_PLAY* play) {
PLAYER_ACTOR* player;
u16 y;
int res;
player = GET_PLAYER_ACTOR(play);
y = player->actor_class.world.angle.y;
res = 0;
if ((y > DEG2SHORT_ANGLE2(135.0f)) && (y < DEG2SHORT_ANGLE2(225.0f)) && (player->actor_class.speed > 0.0f)) { // 0x6000 && 0xA000
res = 1;
}
return res;
}
static int aBGY_check_player(ACTOR* actor, GAME_PLAY* play) {
u16 y;
f32 xOffs;
f32 zOffs;
f32 t;
int res;
PLAYER_ACTOR* player;
player = GET_PLAYER_ACTOR(play);
res = 0;
if (player == NULL) {
return 0;
}
y = player->actor_class.shape_info.rotation.y;
xOffs = SQ(player->actor_class.world.position.x - actor->world.position.x);
zOffs = SQ(player->actor_class.world.position.z - (actor->world.position.z + 60.0f));
t = (xOffs) + (zOffs);
if ((y > DEG2SHORT_ANGLE2(135.0f)) && (y < DEG2SHORT_ANGLE2(225.0f)) && (t < 480.0f)) { // 0x6000 && 0xA000
res = 2;
} else if (t < 1200.0f) {
res = 1;
}
return res;
}
static int aBGY_open_check() {
int res;
res = mEv_CheckEvent(mEv_SPNPC_GYPSY);
res = (res != FALSE) + 1;
return res;
}
static void aBGY_set_talk_info_close_wait(ACTOR* actor) {
rgba_t window_color;
mDemo_Set_msg_num(0x7D5);
mDemo_Set_talk_display_name(FALSE);
mDemo_Set_ListenAble();
window_color.r = 145;
window_color.g = 60;
window_color.b = 40;
window_color.a = 255;
mDemo_Set_talk_window_color(&window_color);
}
static void aBGY_close_wait(STRUCTURE_ACTOR* buggy, GAME_PLAY* play) {
ACTOR* actor;
actor = (ACTOR*)buggy;
if (mDemo_Check(mDemo_TYPE_TALK, actor) == TRUE) {
return;
}
if (aBGY_open_check() == 2) {
if (aBGY_check_player(actor, play) == FALSE) {
return;
}
aBGY_setup_action(buggy, aBGY_ACTION_OPEN_DOOR);
return;
}
if (ABS(actor->player_angle_y) >= DEG2SHORT_ANGLE(45.0f)) { // 0x2000
return;
}
mDemo_Request(mDemo_TYPE_TALK, actor, &aBGY_set_talk_info_close_wait);
}
static void aBGY_open_wait(STRUCTURE_ACTOR* buggy, GAME_PLAY* play) {
ACTOR* actor;
GAME* game;
xyz_t pos;
actor = (ACTOR*)buggy;
game = &play->game;
if (buggy == GET_PLAYER_ACTOR_NOW()->get_door_label_proc(gamePT)) {
aBGY_rewrite_out_data(actor, play);
goto_other_scene(play, &aBGY_buggy_door_data, TRUE);
return;
}
if (mPlib_check_player_actor_main_index_OutDoorMove(play) != FALSE) {
return;
}
if ((aBGY_check_player(actor, play) == 0) || (aBGY_open_check() != 2)) {
aBGY_setup_action(buggy, aBGY_ACTION_CLOSE_DOOR);
return;
}
if ((aBGY_check_player(actor, play) == 2) && (aBGY_check_player2(play) != 0)) {
pos.x = actor->world.position.x;
pos.y = GET_PLAYER_ACTOR(play)->actor_class.world.position.y;
pos.z = actor->world.position.z + 64.0f;
mPlib_request_main_door_type1(game, &pos, -DEG2SHORT_ANGLE(180.0f), TRUE, actor); // 0x8000
}
}
static void aBGY_close_door(STRUCTURE_ACTOR* buggy, GAME_PLAY* play) {
if (buggy->keyframe_state != 1) {
return;
}
aBGY_setup_action(buggy, aBGY_ACTION_WAIT);
}
static void aBGY_open_door(STRUCTURE_ACTOR* buggy, GAME_PLAY* play) {
if (buggy->keyframe_state != 1) {
return;
}
aBGY_setup_action(buggy, aBGY_ACTION_OPEN_WAIT);
}
static void aBGY_setup_action(STRUCTURE_ACTOR* buggy, int action) {
static aSTR_MOVE_PROC process[] = {
&aBGY_close_wait,
&aBGY_open_wait,
&aBGY_close_door,
&aBGY_open_door
};
static cKF_Animation_R_c* animation[] = { &cKF_ba_r_obj_s_uranai, &cKF_ba_r_obj_w_uranai };
static f32 start_idx[] = { 1.0f, 17.0f, 17.0f, 1.0f };
static f32 end_idx[] = { 1.0f, 17.0f, 1.0f, 17.0f };
static f32 framespeed[] = { 0.0f, 0.0f, 0.5f, 0.5f };
int winter;
winter = buggy->season == mTM_SEASON_WINTER;
cKF_SkeletonInfo_R_init(&buggy->keyframe, buggy->keyframe.skeleton, animation[winter], start_idx[action],
end_idx[action], start_idx[action], framespeed[action], 0.0f, cKF_FRAMECONTROL_STOP, NULL);
buggy->action_proc = process[action];
buggy->action = action;
}
static int aBGY_ctrl_light(STRUCTURE_ACTOR* buggy) {
int now_sec = Common_Get(time.now_sec);
return !(now_sec < (64800) && now_sec >= (18000));
}
static void aBGY_actor_move(ACTOR* actor, GAME* game) {
GAME_PLAY* play;
STRUCTURE_ACTOR* buggy;
PLAYER_ACTOR* player;
int bx1;
int bz1;
int bx2;
int bz2;
f32 window;
play = (GAME_PLAY*)game;
buggy = (STRUCTURE_ACTOR*)actor;
player = GET_PLAYER_ACTOR(play);
mFI_Wpos2BlockNum(&bx1, &bz1, actor->world.position);
mFI_Wpos2BlockNum(&bx2, &bz2, player->actor_class.world.position);
if ((mDemo_Check(mDemo_TYPE_SCROLL, &player->actor_class) == FALSE) &&
(mDemo_Check(mDemo_TYPE_SCROLL2, &player->actor_class) == FALSE) &&
(mDemo_Check(mDemo_TYPE_SCROLL3, &player->actor_class) == FALSE) && ((bx1 != bx2) || (bz1 != bz2))) {
Actor_delete(actor);
} else {
buggy->keyframe_state = cKF_SkeletonInfo_R_play(&buggy->keyframe);
buggy->action_proc(buggy, play);
window = (aBGY_ctrl_light(buggy) != 0) ? 1.0f : 0.0f;
chase_f(&buggy->arg0_f, window, 0.019532442f);
}
}
static void aBGY_actor_init(ACTOR* actor, GAME* game) {
mFI_SetFG_common(DUMMY_BUGGY, actor->home.position, FALSE);
aBGY_actor_move(actor, game);
actor->mv_proc = &aBGY_actor_move;
}