Implement & link ac_post_office (#312)

This commit is contained in:
Hexalotl
2024-03-22 13:44:48 -07:00
committed by GitHub
parent 779b0da981
commit 80c63841ea
6 changed files with 581 additions and 1 deletions
+4
View File
@@ -798,6 +798,10 @@ ac_needlework_shop.c:
.text: [0x805B65C4, 0x805B7338]
.rodata: [0x8064AAA0, 0x8064AAE8]
.data: [0x806C6138, 0x806C62D0]
ac_post_office.c:
.text: [0x805B7B0C, 0x805B887C]
.rodata: [0x8064AB18, 0x8064AB58]
.data: [0x806C63C0, 0x806C6558]
ac_radio.c:
.text: [0x805B887C, 0x805B8C7C]
.rodata: [0x8064AB58, 0x8064AB68]
+1 -1
View File
@@ -2,7 +2,7 @@
#define AC_POST_OFFICE_H
#include "types.h"
#include "m_actor.h"
#include "ac_structure.h"
#ifdef __cplusplus
extern "C" {
+1
View File
@@ -2712,6 +2712,7 @@ extern int mNT_check_unknown(mActor_name_t item_no);
#define DUMMY_HANIWA1 (DUMMY_HANIWA0 + 1)
#define DUMMY_HANIWA2 (DUMMY_HANIWA1 + 1)
#define DUMMY_HANIWA3 (DUMMY_HANIWA2 + 1)
#define DUMMY_POST_OFFICE 0xF0FF
#define DUMMY_NEEDLEWORK_SHOP 0xF0FF
#define DUMMY_RESERVE 0xF102
#define DUMMY_SHRINE 0xF103
+117
View File
@@ -0,0 +1,117 @@
#include "ac_post_office.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"
enum {
aPOFF_ACTION_WAIT,
aPOFF_ACTION_OPEN_DOOR_WAIT,
aPOFF_ACTION_OPEN_DOOR,
aPOFF_ACTION_OPEN_UNKNOWN,
aPOFF_ACTION_NUM
};
static void aPOFF_actor_ct(ACTOR* actor, GAME* game);
static void aPOFF_actor_dt(ACTOR* actor, GAME* game);
static void aPOFF_actor_init(ACTOR* actor, GAME* game);
static void aPOFF_actor_draw(ACTOR* actor, GAME* game);
// clang-format off
ACTOR_PROFILE Post_Office_Profile = {
mAc_PROFILE_POST_OFFICE,
ACTOR_PART_ITEM,
ACTOR_STATE_NONE,
POST_OFFICE,
ACTOR_OBJ_BANK_KEEP,
sizeof(STRUCTURE_ACTOR),
&aPOFF_actor_ct,
&aPOFF_actor_dt,
&aPOFF_actor_init,
&aPOFF_actor_draw,
NULL
};
// clang-format on
// clang-format off
static u8 aPOFF_shadow_vtx_fix_flg_table[] = {
TRUE, FALSE, FALSE, TRUE,
FALSE, TRUE, FALSE, TRUE,
TRUE, FALSE, TRUE, FALSE,
FALSE, TRUE, FALSE, FALSE
};
// clang-format on
extern Vtx obj_s_yubinkyoku_shadow_v[];
extern Gfx obj_s_yubinkyoku_shadow_2_model[];
// clang-format off
static bIT_ShadowData_c aPOFF_shadow_data = {
14,
aPOFF_shadow_vtx_fix_flg_table,
60.0f,
obj_s_yubinkyoku_shadow_v,
obj_s_yubinkyoku_shadow_2_model
};
// clang-format on
extern cKF_Skeleton_R_c cKF_bs_r_obj_s_yubinkyoku;
extern cKF_Skeleton_R_c cKF_bs_r_obj_w_yubinkyoku;
static void aPOFF_set_bgOffset(STRUCTURE_ACTOR* office, int idx);
static void aPOFF_setup_animation(STRUCTURE_ACTOR* office, f32 speed);
static void aPOFF_setup_action(STRUCTURE_ACTOR* office, int action);
static int aPOFF_ctrl_light(STRUCTURE_ACTOR* office);
static void aPOFF_actor_ct(ACTOR* actor, GAME* game) {
static cKF_Skeleton_R_c* skl[] = { &cKF_bs_r_obj_s_yubinkyoku, &cKF_bs_r_obj_w_yubinkyoku };
STRUCTURE_ACTOR* office;
office = (STRUCTURE_ACTOR*)actor;
office->season = Common_Get(time.season);
cKF_SkeletonInfo_R_ct(&office->keyframe, skl[office->season == mTM_SEASON_WINTER], NULL, office->work_area,
office->morph_area);
aPOFF_set_bgOffset(office, 1);
actor->world.position.x = actor->world.position.x + -20.0f;
actor->world.position.z = actor->world.position.z + 20.0f;
actor->cull_width = 500.0f;
actor->cull_distance = 500.0f;
office->request_type = 0;
aPOFF_setup_animation(office, 0.0f);
aPOFF_setup_action(office, aPOFF_ACTION_WAIT);
office->keyframe_state = cKF_SkeletonInfo_R_play(&office->keyframe);
office->keyframe_saved_keyframe = 1;
if (aPOFF_ctrl_light(office)) {
office->action = DEG2SHORT_ANGLE(90.0f) - 1; // 0x3FFF
} else {
office->action = DEG2SHORT_ANGLE(0.0f);
}
}
static void aPOFF_actor_dt(ACTOR* actor, GAME* game) {
STRUCTURE_ACTOR* office;
office = (STRUCTURE_ACTOR*)actor;
cKF_SkeletonInfo_R_dt(&office->keyframe);
actor->world.position.x -= -20.0f;
actor->world.position.z -= 20.0f;
}
#include "../src/ac_post_office_move.c_inc"
#include "../src/ac_post_office_draw.c_inc"
+165
View File
@@ -0,0 +1,165 @@
extern Gfx obj_s_yubinkyoku_window_model[];
extern Gfx obj_w_yubinkyoku_window_model[];
static int aPOFF_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) {
GRAPH* graph;
STRUCTURE_ACTOR* office;
f32 inter;
int angle;
int r;
int g;
int b;
Gfx* gfx;
graph = game->graph;
office = (STRUCTURE_ACTOR*)arg;
if (joint_idx == 1) {
angle = office->action;
if (angle == DEG2SHORT_ANGLE(90.0f) - 1) { // 0x3FFF
r = 255;
g = 255;
b = 150;
} else if (angle == DEG2SHORT_ANGLE(0.0f)) {
r = 0;
g = 0;
b = 0;
} else {
inter = (1.0f / (DEG2SHORT_ANGLE(90.0f) - 1)) * angle;
r = (255.0f * inter);
g = (255.0f * inter);
b = (150.0f * inter);
}
OPEN_DISP(graph);
gfx = NOW_POLY_OPA_DISP;
gDPSetPrimColor(gfx++, 0, 0, r, g, b, 255);
SET_POLY_OPA_DISP(gfx);
CLOSE_DISP(graph);
}
if (joint_idx == 7) {
*joint_shape = NULL;
}
return TRUE;
}
static int aPOFF_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_yubinkyoku_window_model, obj_w_yubinkyoku_window_model };
STRUCTURE_ACTOR* office;
GRAPH* graph;
Mtx* mtx;
int angle;
int winter;
int l;
int r;
int g;
int b;
Gfx* gfx;
office = (STRUCTURE_ACTOR*)arg;
graph = game->graph;
if (joint_idx == 7) {
mtx = _Matrix_to_Mtx_new(graph);
if (mtx != NULL) {
angle = office->action;
if (angle == DEG2SHORT_ANGLE(90.0f) - 1) { // 0x3FFF
l = 120;
r = 255;
g = 255;
b = 150;
} else if (angle == DEG2SHORT_ANGLE(0.0f)) {
l = 0;
r = 0;
g = 0;
b = 0;
} else {
r = 255;
g = 255;
b = 150;
l = (1.0f / (DEG2SHORT_ANGLE(90.0f) - 1)) * angle * 120.0f;
}
winter = office->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 aPOFF_actor_draw_ta_set(STRUCTURE_ACTOR* office, GAME_PLAY* play) {
GRAPH* graph = play->game.graph;
OPEN_DISP(graph);
gDPSetTexEdgeAlpha(NEXT_POLY_OPA_DISP, 32);
gDPSetTexEdgeAlpha(NEXT_SHADOW_DISP, 32);
CLOSE_DISP(graph);
}
static void aPOFF_actor_draw_ta_clr(STRUCTURE_ACTOR* office, GAME_PLAY* play) {
GRAPH* graph = play->game.graph;
OPEN_DISP(graph);
gDPSetTexEdgeAlpha(NEXT_POLY_OPA_DISP, 144);
gDPSetTexEdgeAlpha(NEXT_SHADOW_DISP, 144);
CLOSE_DISP(graph);
}
static void aPOFF_actor_draw(ACTOR* actor, GAME* game) {
GRAPH* graph;
cKF_SkeletonInfo_R_c* keyframe;
Mtx* mtx;
Gfx* gfx;
u16* pal;
GAME_PLAY* play;
STRUCTURE_ACTOR* office;
graph = game->graph;
play = (GAME_PLAY*)game;
office = (STRUCTURE_ACTOR*)actor;
keyframe = &office->keyframe;
mtx = GRAPH_ALLOC_TYPE(graph, Mtx, (u32)keyframe->skeleton->num_shown_joints);
if (mtx != NULL) {
pal = Common_Get(clip).structure_clip->get_pal_segment_proc(aSTR_PAL_POST_OFFICE);
_texture_z_light_fog_prim(graph);
aPOFF_actor_draw_ta_set(office, play);
OPEN_DISP(graph);
gfx = NOW_POLY_OPA_DISP;
gSPSegment(gfx++, 8, pal);
SET_POLY_OPA_DISP(gfx);
CLOSE_DISP(graph);
cKF_Si3_draw_R_SV(game, keyframe, mtx, &aPOFF_actor_draw_before, &aPOFF_actor_draw_after, actor);
(*Common_Get(clip).bg_item_clip->draw_shadow_proc)(game, &aPOFF_shadow_data, FALSE);
aPOFF_actor_draw_ta_clr(office, play);
}
}
+293
View File
@@ -0,0 +1,293 @@
// clang-format off
static Door_data_c aPOFF_post_office_door_data = {
SCENE_POST_OFFICE,
4,
FALSE,
0,
{160, 0, 300},
EMPTY_NO,
1,
{0, 0, 0},
};
// clang-format on
extern cKF_Animation_R_c cKF_ba_r_obj_s_yubinkyoku;
extern cKF_Animation_R_c cKF_ba_r_obj_s_yubinkyoku_out;
extern cKF_Animation_R_c cKF_ba_r_obj_w_yubinkyoku;
extern cKF_Animation_R_c cKF_ba_r_obj_w_yubinkyoku_out;
static void aPOFF_set_door_SE_sub(STRUCTURE_ACTOR* office, u16 se_no) {
sAdo_OngenTrgStart(se_no, &office->actor_class.world.position);
}
static void aPOFF_set_doorSE(STRUCTURE_ACTOR* office) {
static f32 chk_pat_in[4] = { 10.0f, 14.0f, 35.0f, 50.0f };
static f32 chk_pat_out[4] = { 2.0f, 8.0f, 33.0f, 40.0f };
static u16 se_no[4] = { 6, 7, 8, 9 };
f32* chk_pat_p;
int i;
switch (office->request_type) {
case 1:
case 3:
chk_pat_p = chk_pat_in;
break;
default:
chk_pat_p = chk_pat_out;
break;
}
for (i = 0; i < 4; i++, chk_pat_p++) {
if (cKF_FrameControl_passCheck_now(&office->keyframe.frame_control, *chk_pat_p) != FALSE) {
aPOFF_set_door_SE_sub(office, se_no[i]);
break;
}
}
}
static void aPOFF_rewrite_out_data(STRUCTURE_ACTOR* office, 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) {
door_data->next_scene_id = Save_Get(scene_no);
door_data->exit_orientation = mSc_DIRECT_SOUTH_WEST;
door_data->exit_type = 0;
door_data->extra_data = 2;
pos.x = office->actor_class.world.position.x - 64.0f;
pos.z = office->actor_class.world.position.z + 64.0f;
pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(pos, 0.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 = POST_OFFICE;
door_data->wipe_type = 1;
}
}
static int aPOFF_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 - 40.0f));
zOffs = SQ(player->actor_class.world.position.z - (actor->world.position.z + 50.0f));
t = (xOffs) + (zOffs);
if ((y > 0x4000) && (y < 0x8000) && (t < 360.0f) && chkTrigger(BUTTON_A) != 0) {
res = 2;
}
return res;
}
static int aPOFF_check_open(STRUCTURE_ACTOR* office, GAME_PLAY* play) {
static int cond[] = { 1, 1, 2, 3 };
switch (office->request_type) {
case 0:
return aPOFF_check_player(&office->actor_class, play);
case 5:
return 0;
default:
return cond[office->request_type - 1];
}
}
static void aPOFF_set_bgOffset(STRUCTURE_ACTOR* office, int idx) {
// clang-format off
static mCoBG_OffsetTable_c height_table_ct[] = {
{ mCoBG_ATTRIBUTE_NONE, 0, 0, 0, 0, 0, 0 },
{ mCoBG_ATTRIBUTE_NONE, 13, 13, 0, 13, 13, 1 },
{ mCoBG_ATTRIBUTE_NONE, 13, 13, 13, 0, 13, 1 },
{ mCoBG_ATTRIBUTE_NONE, 0, 0, 0, 0, 0, 0 },
{ mCoBG_ATTRIBUTE_NONE, 13, 13, 0, 13, 13, 1 },
{ mCoBG_ATTRIBUTE_NONE, 13, 13, 13, 13, 14, 0 },
{ mCoBG_ATTRIBUTE_NONE, 13, 14, 13, 13, 13, 0 },
{ mCoBG_ATTRIBUTE_NONE, 13, 13, 13, 0, 13, 1 },
{ mCoBG_ATTRIBUTE_NONE, 13, 0, 13, 13, 13, 1 },
{ mCoBG_ATTRIBUTE_NONE, 13, 13, 13, 14, 13, 0 },
{ mCoBG_ATTRIBUTE_NONE, 13, 13, 14, 13, 13, 0 },
{ mCoBG_ATTRIBUTE_NONE, 13, 13, 13, 13, 0, 1 },
{ mCoBG_ATTRIBUTE_NONE, 0, 0, 0, 0, 0, 0 },
{ mCoBG_ATTRIBUTE_NONE, 13, 0, 13, 13, 13, 1 },
{ mCoBG_ATTRIBUTE_NONE, 13, 13, 13, 13, 0, 1 },
{ mCoBG_ATTRIBUTE_NONE, 0, 0, 0, 0, 0, 0 }
};
// clang-format on
static mCoBG_OffsetTable_c* height_table[] = { height_table_ct, height_table_ct };
static f32 addX[] = { -80.0f, -40.0f, 0.0f, 40.0f };
static f32 addZ[] = { 80.0f, 40.0f, 0.0f, -40.0f };
mCoBG_OffsetTable_c* offset;
int i;
int j;
xyz_t pos;
offset = height_table[idx];
for (i = 0; i < 4; i++) {
pos.z = office->actor_class.home.position.z + addZ[i];
for (j = 0; j < 4; j++) {
if (j + i * 4 != 0 && j + i * 4 != 3 && j + i * 4 != 12 && j + i * 4 != 15) {
pos.x = office->actor_class.home.position.x + addX[j];
mCoBG_SetPluss5PointOffset_file(pos, *offset, __FILE__, 337);
}
offset++;
}
}
}
static void aPOFF_setup_animation(STRUCTURE_ACTOR* office, f32 speed) {
// clang-format off
static cKF_Animation_R_c* animation[2][2] = {
{ &cKF_ba_r_obj_s_yubinkyoku, &cKF_ba_r_obj_s_yubinkyoku_out },
{ &cKF_ba_r_obj_w_yubinkyoku, &cKF_ba_r_obj_w_yubinkyoku_out }
};
// clang-format on
static f32 start_idx[] = { 1.0f, 25.0f, 1.0f, 1.0f };
static f32 end_idx[] = { 51.0f, 51.0f, 51.0f, 51.0f };
int winter;
int idx;
winter = office->season == mTM_SEASON_WINTER;
switch (office->request_type) {
case 2:
idx = 2;
break;
case 4:
idx = 1;
break;
default:
idx = 0;
break;
}
cKF_SkeletonInfo_R_init(&office->keyframe, office->keyframe.skeleton, animation[winter][idx != 0], start_idx[idx],
end_idx[idx], start_idx[idx], speed, 0.0f, cKF_FRAMECONTROL_STOP, NULL);
}
static void aPOFF_open_door_demo_ct() {
mDemo_Set_house_info(40.0f, 5);
mDemo_Set_camera(CAMERA2_PROCESS_DOOR);
}
static int aPOFF_ctrl_light(STRUCTURE_ACTOR* office) {
int now_sec = Common_Get(time.now_sec);
return !(now_sec < (64800) && now_sec > (18000));
}
static void aPOFF_wait(STRUCTURE_ACTOR* office, GAME_PLAY* play) {
ACTOR* actor;
int request_type;
int check_open;
actor = (ACTOR*)office;
request_type = office->request_type;
if (mDemo_Check(mDemo_TYPE_DOOR, actor) != FALSE) {
if (request_type == 4) {
aPOFF_setup_animation(office, 0.5f);
}
aPOFF_setup_action(office, aPOFF_ACTION_OPEN_DOOR_WAIT);
} else {
check_open = aPOFF_check_open(office, play);
if (check_open == 2) {
mDemo_Request(mDemo_TYPE_DOOR, actor, &aPOFF_open_door_demo_ct);
} else if (check_open == 3) {
if (request_type == 4) {
aPOFF_setup_animation(office, 0.5f);
}
aPOFF_setup_action(office, aPOFF_ACTION_OPEN_DOOR);
}
}
}
static void aPOFF_open_door_wait(STRUCTURE_ACTOR* office, GAME_PLAY* play) {
if (office == GET_PLAYER_ACTOR_NOW()->get_door_label_proc(gamePT)) {
office->request_type = 3;
aPOFF_setup_animation(office, 0.5f);
aPOFF_setup_action(office, aPOFF_ACTION_OPEN_DOOR);
mBGMPsComp_make_ps_wipe(0x249); // TODO: enum/define
}
}
static void aPOFF_open_door(STRUCTURE_ACTOR* office, GAME_PLAY* play) {
if (cKF_SkeletonInfo_R_play(&office->keyframe) == TRUE) {
if (office->request_type == 3) {
aPOFF_rewrite_out_data(office, play);
goto_other_scene(play, &aPOFF_post_office_door_data, FALSE);
aPOFF_setup_action(office, aPOFF_ACTION_OPEN_UNKNOWN);
mDemo_End((ACTOR*)office);
} else {
aPOFF_setup_action(office, aPOFF_ACTION_WAIT);
}
office->request_type = 0;
}
}
static void aPOFF_setup_action(STRUCTURE_ACTOR* office, int action) {
// clang-format off
static aSTR_MOVE_PROC process[] = {
&aPOFF_wait,
&aPOFF_open_door_wait,
&aPOFF_open_door,
(aSTR_MOVE_PROC)&none_proc1
};
// clang-format on
office->action_proc = process[action];
}
static void aPOFF_actor_move(ACTOR* actor, GAME* game) {
STRUCTURE_ACTOR* office;
GAME_PLAY* play;
s16 target;
office = (STRUCTURE_ACTOR*)actor;
play = (GAME_PLAY*)game;
aPOFF_set_doorSE(office);
(*office->action_proc)(office, play);
target = (s16)office->action;
if (aPOFF_ctrl_light(office)) {
chase_s(&target, DEG2SHORT_ANGLE(90.0f) - 1, 320); // 0x3FFF
} else {
chase_s(&target, DEG2SHORT_ANGLE(0.0f), 320);
}
office->action = target;
}
static void aPOFF_actor_init(ACTOR* actor, GAME* game) {
mFI_SetFG_common(DUMMY_POST_OFFICE, actor->home.position, FALSE);
aPOFF_actor_move(actor, game);
actor->mv_proc = aPOFF_actor_move;
}