Merge pull request #320 from Hexalotl/ac_shop

Implement & link ac_shop
This commit is contained in:
Cuyler36
2024-03-30 19:57:16 -04:00
committed by GitHub
6 changed files with 623 additions and 1 deletions
+4
View File
@@ -833,6 +833,10 @@ ac_s_car.c:
.text: [0x805B9098, 0x805B9644]
.rodata: [0x8064AB68, 0x8064AB88]
.data: [0x806C6608, 0x806C66D0]
ac_shop.c:
.text: [0x805B9644, 0x805BA4D8]
.rodata: [0x8064AB88, 0x8064ABD0]
.data: [0x806C66D0, 0x806C6838]
ac_shrine.c:
.text: [0x805BA4D8, 0x805BB8D0]
.rodata: [0x8064ABD0, 0x8064AC18]
+1 -1
View File
@@ -2,7 +2,7 @@
#define AC_SHOP_H
#include "types.h"
#include "m_actor.h"
#include "ac_structure.h"
#ifdef __cplusplus
extern "C" {
+1
View File
@@ -2708,6 +2708,7 @@ extern int mNT_check_unknown(mActor_name_t item_no);
#define DUMMY_HOUSE1 0xF0F4
#define DUMMY_HOUSE2 0xF0F5
#define DUMMY_HOUSE3 0xF0F6
#define DUMMY_SHOP0 0xF0F7
#define DUMMY_HANIWA0 0xF0FB
#define DUMMY_HANIWA1 (DUMMY_HANIWA0 + 1)
#define DUMMY_HANIWA2 (DUMMY_HANIWA1 + 1)
+137
View File
@@ -0,0 +1,137 @@
#include "ac_shop.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 {
aSHOP_ACTION_CLOSE_WAIT,
aSHOP_ACTION_OPEN_WAIT,
aSHOP_ACTION_CLOSE_DOOR,
aSHOP_ACTION_OPEN_DOOR,
aSHOP_ACTION_PL_INTO_WAIT,
aSHOP_ACTION_NUM
};
// clang-format on
static void aSHOP_actor_ct(ACTOR* actor, GAME* game);
static void aSHOP_actor_dt(ACTOR* actor, GAME* game);
static void aSHOP_actor_init(ACTOR* actor, GAME* game);
static void aSHOP_actor_draw(ACTOR* actor, GAME* game);
// clang-format off
ACTOR_PROFILE Shop_Profile = {
mAc_PROFILE_SHOP,
ACTOR_PART_ITEM,
ACTOR_STATE_TA_SET,
SHOP0,
ACTOR_OBJ_BANK_KEEP,
sizeof(STRUCTURE_ACTOR),
&aSHOP_actor_ct,
&aSHOP_actor_dt,
&aSHOP_actor_init,
&aSHOP_actor_draw,
NULL
};
// clang-format on
// clang-format off
static u8 aSHOP_shadow_vtx_fix_flg_table[] = {
TRUE, FALSE, TRUE, FALSE,
TRUE, FALSE, FALSE, TRUE
};
// clang-format on
extern Vtx obj_shop1_shadow_v[];
extern Gfx obj_shop1_shadowT_model[];
// clang-format off
static bIT_ShadowData_c aSHOP_shadow_data = {
8,
aSHOP_shadow_vtx_fix_flg_table,
60.0f,
obj_shop1_shadow_v,
obj_shop1_shadowT_model
};
// clang-format on
extern cKF_Skeleton_R_c cKF_bs_r_obj_s_shop1;
extern cKF_Skeleton_R_c cKF_bs_r_obj_w_shop1;
static void aSHOP_set_bgOffset(STRUCTURE_ACTOR* shop, int offs);
static void aSHOP_setup_action(STRUCTURE_ACTOR* shop, int action);
static int aSHOP_ctrl_light(STRUCTURE_ACTOR* shop);
static void aSHOP_actor_ct(ACTOR* actor, GAME* game) {
static cKF_Skeleton_R_c* skl[] = { &cKF_bs_r_obj_s_shop1, &cKF_bs_r_obj_w_shop1 };
STRUCTURE_ACTOR* shop;
GAME_PLAY* play;
PLAYER_ACTOR* player;
int winter;
int action;
int x;
int z;
shop = (STRUCTURE_ACTOR*)actor;
play = (GAME_PLAY*)game;
player = GET_PLAYER_ACTOR(play);
shop->season = Common_Get(time.season);
action = aSHOP_ACTION_OPEN_WAIT;
winter = shop->season == mTM_SEASON_WINTER;
cKF_SkeletonInfo_R_ct(&shop->keyframe, skl[winter], NULL, shop->work_area, shop->morph_area);
aSHOP_set_bgOffset(shop, 1);
actor->world.position.x = actor->world.position.x + -20.0f;
actor->world.position.z = actor->world.position.z + 20.0f;
actor->talk_distance = 80.0f;
actor->cull_width = 550.0f;
actor->cull_radius = 550.0f;
if (mSP_ShopOpen() != 2) {
action = aSHOP_ACTION_CLOSE_WAIT;
}
x = (int)(shop->actor_class.world.position.x - 68.29f);
z = (int)(shop->actor_class.world.position.z + 68.29f);
if ((int)player->actor_class.world.position.x == x && (int)player->actor_class.world.position.z == z) {
action = aSHOP_ACTION_OPEN_WAIT;
}
aSHOP_setup_action(shop, action);
if (aSHOP_ctrl_light(shop)) {
shop->arg0 = DEG2SHORT_ANGLE(90.0f) - 1;
} else {
shop->arg0 = DEG2SHORT_ANGLE(0.0f);
}
shop->keyframe_state = cKF_SkeletonInfo_R_play(&shop->keyframe);
shop->keyframe_saved_keyframe = 1;
}
static void aSHOP_actor_dt(ACTOR* actor, GAME* game) {
STRUCTURE_ACTOR* shop;
shop = (STRUCTURE_ACTOR*)actor;
cKF_SkeletonInfo_R_dt(&shop->keyframe);
actor->world.position.x = actor->world.position.x - -20.0f;
actor->world.position.z = actor->world.position.z - 20.0f;
}
#include "../src/ac_shop_move.c_inc"
#include "../src/ac_shop_draw.c_inc"
+145
View File
@@ -0,0 +1,145 @@
extern Gfx obj_s_shop1_window_model[];
extern Gfx obj_w_shop1_window_model[];
static int aSHOP_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* shop;
GRAPH* graph;
f32 inter;
int angle;
int r;
int g;
int b;
Gfx* gfx;
shop = (STRUCTURE_ACTOR*)arg;
graph = game->graph;
if (joint_idx == 5) {
angle = shop->arg0;
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;
gDPSetEnvColor(gfx++, r, g, b, 0);
SET_POLY_OPA_DISP(gfx);
CLOSE_DISP(graph);
} else if (joint_idx == 6) {
*joint_shape = NULL;
}
return TRUE;
}
static int aSHOP_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_shop1_window_model, obj_w_shop1_window_model };
STRUCTURE_ACTOR* office;
GRAPH* graph;
Mtx* mtx;
int angle;
int winter;
int l;
int r;
int g;
int b;
int a;
Gfx* gfx;
office = (STRUCTURE_ACTOR*)arg;
graph = game->graph;
if (joint_idx == 6) {
mtx = _Matrix_to_Mtx_new(graph);
if (mtx != NULL) {
angle = office->arg0;
if (angle == DEG2SHORT_ANGLE(90.0f) - 1) { // 0x3FFF
l = 120;
r = 255;
g = 255;
b = 150;
a = 255;
} else if (angle == DEG2SHORT_ANGLE(0.0f)) {
l = 0;
r = 0;
g = 0;
b = 0;
a = 255;
} else {
r = 255;
g = 255;
b = 150;
a = 255;
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, a);
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 aSHOP_actor_draw(ACTOR* actor, GAME* game) {
GRAPH* graph;
cKF_SkeletonInfo_R_c* keyframe;
Mtx* mtx;
Gfx* gfx;
u16* pal;
GAME_PLAY* play;
STRUCTURE_ACTOR* shop;
graph = game->graph;
play = (GAME_PLAY*)game;
shop = (STRUCTURE_ACTOR*)actor;
keyframe = &shop->keyframe;
mtx = GRAPH_ALLOC_TYPE(graph, Mtx, (u32)keyframe->skeleton->num_shown_joints);
if (mtx == NULL) {
return;
}
pal = Common_Get(clip).structure_clip->get_pal_segment_proc(aSTR_PAL_SHOP1);
_texture_z_light_fog_prim_npc(graph);
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, &aSHOP_actor_draw_before, &aSHOP_actor_draw_after, actor);
(*Common_Get(clip).bg_item_clip->draw_shadow_proc)(game, &aSHOP_shadow_data, FALSE);
}
+335
View File
@@ -0,0 +1,335 @@
extern cKF_Animation_R_c cKF_ba_r_obj_s_shop1;
extern cKF_Animation_R_c cKF_ba_r_obj_w_shop1;
// clang-format off
static Door_data_c aSHOP_shop_door_data = {
SCENE_SHOP0,
mSc_DIRECT_NORTH,
FALSE,
0,
{160,0,300},
EMPTY_NO,
1,
{0,0,0},
};
// clang-format on
static void aSHOP_set_bgOffset(STRUCTURE_ACTOR* shop, int offs) {
// clang-format off
static mCoBG_OffsetTable_c height_table_ct[] = {
{ mCoBG_ATTRIBUTE_NONE, 0, 0, 0, 0, 0, 0 },
{ mCoBG_ATTRIBUTE_NONE, 12, 12, 0, 12, 12, 1 },
{ mCoBG_ATTRIBUTE_NONE, 12, 12, 12, 0, 12, 1 },
{ mCoBG_ATTRIBUTE_NONE, 0, 0, 0, 0, 0, 0 },
{ mCoBG_ATTRIBUTE_NONE, 12, 12, 0, 12, 12, 1 },
{ mCoBG_ATTRIBUTE_NONE, 12, 12, 12, 12, 12, 0 },
{ mCoBG_ATTRIBUTE_NONE, 12, 12, 12, 12, 12, 0 },
{ mCoBG_ATTRIBUTE_NONE, 12, 12, 12, 0, 12, 1 },
{ mCoBG_ATTRIBUTE_NONE, 12, 0, 12, 12, 12, 1 },
{ mCoBG_ATTRIBUTE_NONE, 12, 12, 12, 12, 12, 0 },
{ mCoBG_ATTRIBUTE_NONE, 12, 12, 12, 12, 12, 0 },
{ mCoBG_ATTRIBUTE_NONE, 12, 12, 12, 12, 0, 1 },
{ mCoBG_ATTRIBUTE_NONE, 0, 0, 0, 0, 0, 0 },
{ mCoBG_ATTRIBUTE_NONE, 12, 0, 12, 12, 12, 1 },
{ mCoBG_ATTRIBUTE_NONE, 12, 12, 12, 12, 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[] = { -(mFI_UT_WORLDSIZE_X_F * 2.0f), -mFI_UT_WORLDSIZE_X_F, 0.0f, mFI_UT_WORLDSIZE_X_F };
static f32 addZ[] = { (mFI_UT_WORLDSIZE_Z_F * 2.0f), mFI_UT_WORLDSIZE_Z_F, 0.0f, -mFI_UT_WORLDSIZE_Z_F };
mCoBG_OffsetTable_c* offset;
int i;
int j;
xyz_t pos;
offset = height_table[offs];
for (i = 0; i < 4; i++) {
pos.z = shop->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 = shop->actor_class.home.position.x + addX[j];
mCoBG_SetPluss5PointOffset_file(pos, *offset, __FILE__, 221);
}
offset++;
}
}
}
static void aSHOP_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_WEST;
door_data->exit_type = 0;
door_data->extra_data = 3;
pos.x = actor->world.position.x - 68.29f;
pos.z = actor->world.position.z + 68.29f;
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 = SHOP0;
door_data->wipe_type = 1;
mBGMPsComp_make_ps_wipe(0x2168);
}
static int aSHOP_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(90.0f)) && (y < DEG2SHORT_ANGLE2(180.0f)) &&
(player->actor_class.speed > 0.0f)) { // 0x6000 && 0xA000
res = 1;
}
return res;
}
static int aSHOP_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 - 38.0f));
zOffs = SQ(player->actor_class.world.position.z - (actor->world.position.z + 42.0f));
t = (xOffs) + (zOffs);
if ((y > DEG2SHORT_ANGLE2(90.0f)) && (y < DEG2SHORT_ANGLE2(180.0f)) && (t < 550.0f)) {
res = 1;
}
return res;
}
static void aSHOP_set_talk_info_close_wait(ACTOR* actor) {
rgba_t window_color;
int msg_no;
int now_sec;
int status;
now_sec = Common_Get(time.now_sec);
if (mSP_CheckFukubikiDay() != FALSE) {
if (now_sec >= (6 * mTM_SECONDS_IN_HOUR)) {
msg_no = mSP_ShopOpen() == mSP_SHOP_STATUS_PRE ? 0x7D6 : 0x7D7;
} else {
msg_no = 0x7CD;
}
} else {
switch (mSP_ShopOpen()) {
case mSP_SHOP_STATUS_PRE: // 0
case mSP_SHOP_STATUS_END: // 1
msg_no = 0x7CD;
break;
case mSP_SHOP_STATUS_PREEVENT: // 4
msg_no = 0x7D1;
break;
case mSP_SHOP_STATUS_ENDEVENT: // 5
msg_no = 0x7D9;
break;
case mSP_SHOP_STATUS_RENEW: // 3
msg_no = 0x7D8;
break;
default:
msg_no = 0x7CD;
break;
}
}
mDemo_Set_msg_num(msg_no);
mDemo_Set_talk_display_name(FALSE);
mDemo_Set_camera(TRUE);
mPlib_Set_able_hand_all_item_in_demo(TRUE);
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 int aSHOP_ctrl_light(STRUCTURE_ACTOR* shop) {
int now_sec;
int res;
now_sec = Common_Get(time.now_sec);
res = FALSE;
if (mEv_CheckArbeit() == TRUE) {
if ((mSP_ShopOpen() == mSP_SHOP_STATUS_OPEN || mSP_ShopOpen() == mSP_SHOP_STATUS_OPENEVENT)) {
if ((now_sec >= (18 * mTM_SECONDS_IN_HOUR) || now_sec < (5 * mTM_SECONDS_IN_HOUR))) {
res = TRUE;
}
}
} else if (now_sec >= (18 * mTM_SECONDS_IN_HOUR) || now_sec < (5 * mTM_SECONDS_IN_HOUR)) {
if (shop->action == aSHOP_ACTION_PL_INTO_WAIT) {
res = TRUE;
} else if (mSP_ShopOpen() == mSP_SHOP_STATUS_OPEN || mSP_ShopOpen() == mSP_SHOP_STATUS_OPENEVENT) {
res = TRUE;
}
}
return res;
}
static void aSHOP_close_wait(STRUCTURE_ACTOR* shop, GAME_PLAY* play) {
ACTOR* actor;
actor = (ACTOR*)shop;
if (mDemo_Check(mDemo_TYPE_TALK, actor) == TRUE) {
return;
}
if ((mSP_ShopOpen() == mSP_SHOP_STATUS_OPEN) || (mSP_ShopOpen() == mSP_SHOP_STATUS_OPENEVENT)) {
aSHOP_setup_action(shop, aSHOP_ACTION_OPEN_DOOR);
return;
}
if (aSHOP_check_player(actor, play) == mSP_SHOP_STATUS_PRE) {
return;
}
mDemo_Request(mDemo_TYPE_TALK, actor, &aSHOP_set_talk_info_close_wait);
}
static void aSHOP_open_wait(STRUCTURE_ACTOR* shop, GAME_PLAY* play) {
ACTOR* actor;
GAME* game;
xyz_t pos;
actor = &shop->actor_class;
game = &play->game;
if (mPlib_check_player_actor_main_index_OutDoorMove(play) != FALSE) {
return;
}
if (mSP_ShopOpen() != mSP_SHOP_STATUS_OPEN && mSP_ShopOpen() != mSP_SHOP_STATUS_OPENEVENT) {
sAdo_OngenTrgStart(8, &actor->world.position);
aSHOP_setup_action(shop, aSHOP_ACTION_CLOSE_DOOR);
return;
}
if (aSHOP_check_player(actor, play) == 1 && aSHOP_check_player2(play) == TRUE) {
pos.x = actor->world.position.x - 50.0f;
pos.y = GET_PLAYER_ACTOR(play)->actor_class.world.position.y;
pos.z = actor->world.position.z + 50.0f;
mSP_SetTanukiShopStatus();
if (mPlib_request_main_door_type1(game, &pos, DEG2SHORT_ANGLE(135.0f), TRUE, actor) == 0) { // 0x6000
return;
}
aSHOP_setup_action(shop, aSHOP_ACTION_PL_INTO_WAIT);
}
}
static void aSHOP_close_door(STRUCTURE_ACTOR* shop, GAME_PLAY* play) {
if (shop->keyframe_state != 1) {
return;
}
sAdo_OngenTrgStart(9, &shop->actor_class.world.position);
aSHOP_setup_action(shop, aSHOP_ACTION_CLOSE_WAIT);
}
static void aSHOP_open_door(STRUCTURE_ACTOR* shop, GAME_PLAY* play) {
if (shop->keyframe_state != 1) {
return;
}
aSHOP_setup_action(shop, aSHOP_ACTION_OPEN_WAIT);
}
static void aSHOP_pl_into_wait(STRUCTURE_ACTOR* shop, GAME_PLAY* play) {
if (shop != GET_PLAYER_ACTOR_NOW()->get_door_label_proc(gamePT)) {
return;
}
aSHOP_rewrite_out_data(&shop->actor_class, play);
goto_other_scene(play, &aSHOP_shop_door_data, FALSE);
}
static void aSHOP_setup_action(STRUCTURE_ACTOR* shop, int action) {
static cKF_Animation_R_c* ani[] = { &cKF_ba_r_obj_s_shop1, &cKF_ba_r_obj_w_shop1 };
static f32 anime_spd[] = { 0.0f, 0.0f, 0.5f, 0.5f, 0.0f };
static f32 set[] = { 1.0f, 16.0f, 16.0f, 1.0f, 16.0f };
static f32 end[] = { 1.0f, 16.0f, 1.0f, 16.0f, 16.0f };
static aSTR_MOVE_PROC process[] = { &aSHOP_close_wait, &aSHOP_open_wait, &aSHOP_close_door, &aSHOP_open_door,
&aSHOP_pl_into_wait };
int winter;
winter = shop->season == mTM_SEASON_WINTER;
cKF_SkeletonInfo_R_init(&shop->keyframe, shop->keyframe.skeleton, ani[winter], 1.0f, end[action], set[action],
anime_spd[action], 0.0f, cKF_FRAMECONTROL_STOP, NULL);
shop->action_proc = process[action];
shop->action = action;
}
static void aSHOP_actor_move(ACTOR* actor, GAME* game) {
STRUCTURE_ACTOR* shop;
GAME_PLAY* play;
s16 target;
xyz_t pos;
shop = (STRUCTURE_ACTOR*)actor;
play = (GAME_PLAY*)game;
shop->keyframe_state = cKF_SkeletonInfo_R_play(&shop->keyframe);
shop->keyframe_saved_keyframe = shop->keyframe.frame_control.current_frame;
(*shop->action_proc)(shop, play);
target = (s16)shop->arg0;
if (aSHOP_ctrl_light(shop)) {
chase_s(&target, DEG2SHORT_ANGLE(90.0f) - 1, 320); // 0x3FFF
} else {
chase_s(&target, DEG2SHORT_ANGLE(0.0f), 320);
}
shop->arg0 = target;
}
static void aSHOP_actor_init(ACTOR* actor, GAME* game) {
mFI_SetFG_common(DUMMY_SHOP0, actor->home.position, FALSE);
aSHOP_actor_move(actor, game);
actor->mv_proc = aSHOP_actor_move;
}